On the other systems I code for (win, mac, linux) there is a database of timezone information that I can query to figure out the timezone in effect at a particular point in history. I can use that to convert a historical date to it’s correct local time, even if the prevailing timezone is different to the current timezone (ie the historical date was during daylight savings and it’s currently not in DST).
What tools does Haiku give me to do that? Or do I need some third party library to get the DST info I need?
I’ve had a look at BTimeZone and it seems super basic. No tools for local<->UTC conversion. Or even when the DST/non-DST changes happen each year.
It’s possible the BTimeZone class is missing a method. @pulkomandy is the one who refactored it to use ICU all those years ago, maybe he can suggest what modifications should be done.
The timezone data is packaged inside ICU, it is sad to need a second copy of it in a separate package. Supporting Linux applications without changes is making Haiku more bloated and full of legacy things than it could be. Oh well.
I think I only implemented just what was needed to get the Locale and Time preferences working.
I don’t know what you need exactly. The way I think about time in UNIX systems is that timestamps are always a number of seconds since january 1st 1970 in UTC. So, you can use the localtime function to convert such a timestamp into a local date representation. Or for converting to a string you could use BDateTimeFormat: DateTimeFormat.h « locale « os « headers - haiku - Haiku's main repository
It looks like BDate supports creating a BDate object from a time_t timestamp and either the UTC or a local timezone, but not any other arbitrary timezone: DateTime.h « support « os « headers - haiku - Haiku's main repository and that is completely missing from BTime and BDateTime.
So your only hope is manually applying the OffsetFromGMT() from the BTimeZone object at the moment
The tcl package also contains timezone data too (under lib/tcl8.6/tzdata). I’ve tried first to make Python use that, but TCL’s data is in plain-text (not “zic compiled” as on the timezone_data package, that’s what Python expects, as I found out later). [1]
Then I thought of just adding a “python-package” recipe for tzdata, but then noticed that timezone_data already was on depot (and supposedly of wider appeal/usefullness than just Python’s tzdata).
Seems there’s a PyICU extension what we could use to leaverage the system-wide ICU libs/data, but while useful on its own merit, doesn’t seems to be a way to make Python Standard Library use that instead of “zic-compiled tzdb/zoneinfo”. [2]
[1] Someone volunteers to investigate if it’s possible to make tcl use timezone_data instead of packaging its own files? Edit: tcl’s tzdata files are just IANA/ICANN files parsed via tools/tclZIC.tcl, so no chance of centralizing that one, it seems.
[2] If someone finds a way… or another alternative, let me know. Albeit, to note:
Python considered and discarded the idea of using the Windows provided ICU API, due to the lack of functions that provided direct access to the underlying time zone data. So, even if Haiku’s ICU integration provides such direct access, we can’t just use it with Python without some serious patching.
Last edit: For better or worse,IANA/ICANN’s tzdb/zoneinfo seems to be widely used in one way or another. To try and keep only one central copy seems like the best we can realistically hope?
So I wrote a parser this afternoon. It works well enough for my timezone. But it’s probably not well enough tested for others. Unfortunately the timezone_data files aren’t installed by default. But at least I don’t have to rely on the broken linux libs to try and read it anymore.
Still if a better solution comes along I’m all ears.
I guess it would be kinda funny if: struct tm *localtime(const time_t *timep); from time.h actually does what I want.
timegm and gmtime to convert time_t to/from struct tm in UTC (no timezone offset is applied)
mktime and localtime to convert time_t to/from local timezone
So… yes localtime_r does what I want. It gives me the right offset from UTC for historical dates. And the extra little trick once you have that struct tm *t to get the timezone in effect is:
auto timezone = timegm(t) - mktime(t)
That’s in seconds… divide by whatever for minutes and hours.
That said having good access to when the daylight savings changes is still needed elsewhere in the code base, so it’s not entirely wasted effort. Mainly for the calendar component of Scribe. And more specifically in resolving recurring events that overlap different DST time zones.