pavkam / tzdb Goto Github PK
View Code? Open in Web Editor NEWDelphi/FPC Time Zone Database
Home Page: https://www.iana.org/time-zones
License: BSD 3-Clause "New" or "Revised" License
Delphi/FPC Time Zone Database
Home Page: https://www.iana.org/time-zones
License: BSD 3-Clause "New" or "Revised" License
Some TZs have second-based biases. This needs to be supported in GetAbbreviation
G'day Alex,
We try to apply each IANA DB version as they are published. I've written a utility that takes the download and performs all the steps we need to get it compile in the right places. This includes running TZcompile against the "latest DB".
Many times the compile step will fail with a message like:
We've identified three Links that are problematic:
The problem is with the data in Backward and Backzone files. We commented out the lines in these files, and the TZcompile completes AOK.
The two files change infrequently, but when they do we lose our mods and the TZcompile exception is raised again.
Annoying but not a show stopper. I apologise for not drilling into the code yet to work out a more permanent solution...
Below are some scans showing the duplicate Links.
Cheers, Paul
There is a new release of TZ data updated at 2020.
I'm new to GIT so I write this problem here.
Please move this issue somewhere else more appropriate in the repository if it is necessary.
Please publish some kind of HOW-TO document on updating the TZ database ny oneself.
Thanks.
I would like to have the latest version included in the project. I would provide a PR but I don't know the exact steps to generate the .inc file as I am not very familiar with delphi programming.
G'day all,
We've been trying to install the 2019b database with v1.8.2018c of Alex's excellent toolset, but TZcompile just kept shutting down. Eventually we tracked the root of the problem to the TzStrToDay function in Tzcompile\TZSchema.pas, which objects to the "Fri<=1" in the Asia file.
Doing a BCompare on "Asia" for 2019a and 2019b shows this is new code. There do not seem to be any other "Day<=nn" tests in the IANA source.
As a workaround we've set the test to "1" for now. Any suggestions on best way to fix the code? Is "Day<=nn" going to become a "thing"? Do we need to enhance TzStrToDay?
Cheers, Paul
I'm working on the development of a software that uses the TZDB for Delphi to deal with the timezones' management, and I'd like to have your opinion about a problem that we are facing.
In a procedure, in order to decompose the periods of a timezone, we have to know the timezone's year of a UTC DateTime.
To do so, we are using these commands :
thisBundledTimezone := TBundledTimeZone.GetTimeZone('America/Los_Angeles'); timeZoneYear := YearOf(IncMinute(aUTCDateTime, Round(thisBundledTimezone.UtcOffset.TotalMinutes)));
This is fine if the program is running on Windows, but it crashes on Linux.
The error occurs when we're trying to get the UtcOffset. The TBundledTimeZone can't read the
FPeriods[I] in the function GetPeriodAndRule.
The thing is that FPeriods is a TList that is not typed (with TCompiledPeriod) and Delphi can't use it this way with Linux.
We can by the way see a warning when compiling a project that includes TZDB.pas, telling that TList is deprecated.
We have solved the problem by modifying the TZDB.pas unit, but that's quite a lot of changes in the declarations.
For your information, the Decomposer.pas unit doesn't have any problem with Linux because it is already working with typed TLists (function Decompose).
The wiki needs to be updated to reflect the new code added.
Also add a couple of samples for the new functions.
I'm trying to create a birth chart for Diego Armando Maradona 30 October 1960 at 07:05
The data on IANA says that at the day/time of birth it was active the daylight saving time (+ 1 hour), so the correct time is ADT h3w (GMT-3)
The program of visualization says that in 1960 there was not any daylight saving time active.
These are the data of the time zone active onto IANA:
Buenos Aires DLST From 01/10/1946 00:00 to 01/10/1963 00:00
Please double check the data because it seems to be a problem of reliability of your precious project.
I am having problems building for Delphi Xe2.
Your samples appear to be very dated and even TTimeZone has been replaced with TBundledTimeZone, I guess.
After adapting the sample exercise from your readme.md
var
LTimeZone: TBundledTimeZone;
begin
LTimeZone := TBundledTimeZone.GetTimeZone('Africa/Cairo');
WriteLn(LTimeZone.ToUniversalTime(Now));
I receive an invalid floating point exception here.
{ Extract the last millisecond in the end to mark the end of the period. }
LEnd := IncMilliSecond(LEnd, -1);
Any idea what I am doing wrong?
An extra comma can appear after the last item. I have fixed it in TZSchema.pas by adding a new local integer variable nFamilies
. Then before the loop to generate this array add:
nFamilies := FRuleFamilies.Count - LGhosts;
and instead of the test to write the comma:
Dec(nFamilies);
if nFamilies > 0 then Write(LFile, ',');
Bug in TZDB 2020a
Crash in TBundledTimeZone.ToLocalTime(const ADateTime: TDateTime)
When using the date/time '2018-12-31 22:18:01' (which causes a switch to next year 2019).
Time Zone: "Stockholm"
Any chance that in TZDB.pas all Delphi units are fully qualified - SysUtils -> System.SysUtils?
There are only 17 places :) to make the file "more" correct - for us people who do not want any aliases.
Thanks - and great work.
Hello,
Will it be possible to have a new version with 2024a data?
Thanks & Regards,
Ertan
Hello,
New Zealand could not be identified as a timezone using a code line below with current version of the sources.
PickupDateTime := TBundledTimeZone.GetTimeZone(FData.bookings[I].pickup_date_time_zone).ToLocalTime(FData.bookings[I].pickup_date_time);
I could not clearly understand reason of the source as it is using 2020d version of the time zone database.
Any help is appreciated.
Thanks & Regards,
Ertan
TZdb.pas Extract.txt
My last word on this - promise!
My speculation that the new Rule should be "Fri<=29" with Mar (rather than Apr) has been knocked out. IANA 2019b is correct according to Knesset documents.**
But as TZdb can now handle rules like the one I proposed, I thought I should test the code against this (we only tested "Fri<=1" with Apr the other day).
I editted Asia file, and changed the line thusly:
### pmh Rule Zion 2005 2012 - Apr Fri<=1 2:00 1:00 D
Rule Zion 2005 2012 - Mar Fri<=29 2:00 1:00 D
I recompiled with TZcompile, and tested with TZvisualizer.
For the years the rule affects I got these Start DST dates:
Friday, 4 March 2005
Friday, 3 March 2006
Friday, 2 March 2007
Friday, 7 March 2008
Friday, 6 March 2009
Friday, 5 March 2010
Friday, 4 March 2011
Friday, 2 March 2012
A bit of digging around showed me that the compiler had correctly created the entries in TZdb.inc, but that it was the new function in TZdb.pas (EncodeDateMonthFirstDayOfWeekBefore) that was not working for the larger numbers.
I amended TZdb.pas (extract attached) and retested:
Friday, 25 March 2005
Friday, 24 March 2006
Friday, 23 March 2007
Friday, 28 March 2008
Friday, 27 March 2009
Friday, 26 March 2010
Friday, 25 March 2011
Friday, 23 March 2012
These dates conform to the rule (dd is <= 29, mm is March and weekday is Fri). The changed code was regression tested for rule "Fri<=1 Apr" and produced results the same as the original.
Should I "pull" the source and apply my version of the function?
Cheers, Paul
** I got a very frosty, unhelpful response from IANA. Apparently I contacted the wrong person. While I was hunting around for an alternative place to pose my question, I came across another source (TimeAndDate.com) that confirmed all the original dates for Start of DST from 2005-12.
Turns out Wikipedia is wrong. But getting that corrected is a battle I don't want to front up for!
pmh
I think we've jumped ahead a lot of IANA releases :-)
Cheers, Paul
The next logical step is to get rid of the compiled period and rules. There is a potential data loss in regards to multi-period years and years that end in a rule right at midnight 31st of December.
Thought I haven't seen any of those if would be nice to have all types of rules working.
I am using RadStudio 10.3.3 (C++ Builder) to compile TZDB.pas and use, but I get an error on the following:
40 {$IF DECLARED(CompilerVersion)}
41 {$IF CompilerVersion >= 22} // Delphi XE +
42 {$DEFINE TZDB_SUPPORTED_COMPILER}
43 {$DEFINE DELPHI}
44 {$IFEND}
45 {$ENDIF}
The errors:
[Pascal Error] TZDB.pas(41,32): E2026 Constant Expression expected
[Pascal Error] TZDB.pas(50,4): E1054 TZDB requires at least Delphi XE or FreePascal 3.0 to compile!
[Pascal Error] TZDB.pas(69,5): F2613 Unit 'FGL' not found.
I don't know if this is a problem in RadStudio 10.3.3 or if it is a problem with the C++ Builder side, but I can simply comment out the lines of code 40,41,44,45 and compile no problem. But I don't like doing this because whenever I update the source it will be a problem.
Any ideas?
I suggest adding a file https://github.com/unicode-org/icu/blob/main/icu4c/source/tools/tzcode/icuzones for compatibility with ICU zones. I did it myself, but I think it will be useful if this file is already immediately added to the assembly.
tzdb cannot compile in Android and iOS platform due to the usage of unit contnrs. I think TBucketList may be replaced by TDictionary.
I needed to convert some date times to one timezone to another, and I found your TZDB project.
It works like a charm, so It have saved me a lot of time. Many thanks 😊
But I’m missing one thing. I have tried to implement what I need, inheriting my own class from TBundledTimeZone, but all the data I need is Private or under the implementation section, so I can’t access it without modifying the original sources.
What I am missing is a function to get the year/date when a Standard or Daylight rule start for a given year.
Let me explain… I have seen that the function DaylightTimeStart(Year) returns the day and time of the Daylight segment for the given year, but I need to know when the rule applied to get that Daylight segment started to be applied.
Browsing TZDB.pas, I have seen that that info is in CFamily_X_Arr:
{ Date-bound rules for EU family }
CFamily_1_Arr: array[0 .. 5] of TYearBoundRule = (
(FStart: 1977; FEnd: 1980; FRule: @CRules[50]),
(FStart: 1977; FEnd: 1977; FRule: @CRules[51]),
(FStart: 1978; FEnd: 1978; FRule: @CRules[52]),
(FStart: 1979; FEnd: 1995; FRule: @CRules[51]),
(FStart: 1981; FEnd: 9999; FRule: @CRules[53]),
(FStart: 1996; FEnd: 9999; FRule: @CRules[54])
);
This info is important to properly define a timezone in a iCalendar (.ics) file.
Would it be possible to include the function I need (something like DaylightRuleStartYear/Date - StandardRuleStartYear/Date) in next distributions?
I think it could be helpful for many people too.
In 2010 there is a rule that starts the DST but the library identifies it as Standard.
In 2011 there is a complicated combination of 2 rules and a period switch at the end of the year.
Need to investigate whether 24:00 is treated accordingly.
Hello,
When i tried to execute the example:
var
LAmsterdam: TTimeZone;
begin
LAmsterdam := TBundledTimeZone.GetTimeZone('Europe/Amsterdam');
...
...
end;
I got the error saying that LAmsterdam is a TTimeZone not compatible with TBundledTimeZone.
Do you know how to fix this?
Hi,
the ToISO8601Format function returns a string where time and date are separated by a space. According to the iso 8601 spec, the date and time should be separated by the letter "T". Could you change that in the CZFormat and CFullFormat in the implementation of the function?
Also, the documentation (in dist/TZDB.pas) says that the ADateTime should be a utc timestamp. However, the function only appends the timezone bias, but does not convert the date/time from utc to local. That means that if you pass a utc TDateTime into the function, it will output the utc date and time but with the local timezone bias, resulting in the wrong time. Could you change the documentation to say that the function accepts a local TDateTime (and not a utc one)? The function then works as expected. I think it actually makes more sense to pass a local TDateTime into the function, as it only formats it to an iso 8601 string. It doesn't have to convert the TDateTime from utc to local, since there's already another function to do that.
I want update library to version 2020f, but when I run script it fails with error:
TTZDBTest Time:00.058 N:38 E:0 F:1 I:0
00.003 Test_Africa_Accra_1997 Failed: "DST name differs for 0 period." expected: <GMT> but was: <>
Exception: "DST name differs for 0 period." expected: <GMT> but was: <>
at $0000000000433E5A
TTZDB_St_Johns_2018_Test Time:00.002 N:13 E:0 F:0 I:0
TTZDB_London_2018_Test Time:00.002 N:13 E:0 F:0 I:0
TTZDB_Canberra_2018_Test Time:00.003 N:13 E:0 F:0 I:0
TTZDB_NewYork_2018_Test Time:00.002 N:13 E:0 F:0 I:0
Number of run tests: 90
Number of errors: 0
Number of failures: 1
List of failures:
Failure:
Message: TTZDBTest.Test_Africa_Accra_1997: "DST name differs for 0 period." expected: <GMT> but was: <>
Exception class: EAssertionFailedError
at $0000000000433E5A
[ERR] Tests failed! Please correct the errors before continuing.
There are also a few errors with aliases (are they critical?):
ERROR: Alias "Africa/Asmera" already points to zone "Africa/Asmara". Cannot reassign to zone "Africa/Nairobi".
ERROR: Alias "Antarctica/South_Pole" already points to zone "Antarctica/McMurdo". Cannot reassign to zone "Pacific/Auckland".
ERROR: Alias "Asia/Chungking" already points to zone "Asia/Chongqing". Cannot reassign to zone "Asia/Shanghai".
ERROR: Alias "UTC" already points to zone "Etc/UTC". Cannot reassign to zone "Etc/GMT".
and script can't find two files during update (it seems, they was removed as obsolete):
cp: cannot stat './iana_temp/pacificnew': No such file or directory
cp: cannot stat './iana_temp/systemv': No such file or directory
Consider this test function.
procedure TForm1.Button1Click(Sender: TObject);
var
tz: TBundledTimeZone;
d: TDateTime;
begin
tz := TBundledTimeZone.Create('America/Vancouver');
d := tz.ToUniversalTime(StrToDateTime('3/11/2012 1:06:32 AM'));
d := tz.ToUniversalTime(StrToDateTime('3/11/2012 2:06:32 AM'));
tz.Free;
end;
=== What is the expected output? What do you see instead? ===
The first line will produce an ELocalTimeInvalid exception; the second will not. This is the opposite of the correct behaviour. At 2 AM local time, the clock rolls forward to 3 AM, so local times >= 2 AM and < 3AM should be invalid.
=== What version of the product are you using? On what operating system? ===
Delphi 7
Windows 7
TZDB 1.8
=== Please provide any additional information below. ===
I was able to correct the problem by changing the following lines 681-683 in TZDB.pas in
function TCompiledRule.GetLocalTimeType(const ADateTime: TDateTime): TLocalTimeType :
< if (FNext <> nil) and (FNext.FOffset > FOffset) and
< (CompareDateTime(ADateTime, IncSecond(FNext.FStartsOn, FOffset - FNext.FOffset)) >= 0) then
< Result := lttInvalid
if (FPrev <> nil) and (FOffset > FPrev.FOffset) and
(CompareDateTime(ADateTime, FStartsOn) >= 0) and
(CompareDateTime(ADateTime, IncSecond(FStartsOn, FOffset - FPrev.FOffset)) < 0) then
Result := lttInvalid
I am not sure if this is the correct fix, but it does appear to correctly address the boundary cases and makes intuitive sense. By the time this edge case is tested, the contents of FPrev / Self / FNext have already advanced, for which the current code fails to account.
(As a side note, I was not able to add breakpoints to tzdb.pas -- despite checking for CRLF line endings, removing DCU files, enabling debug info, etc. Would be interested to know if there is something about tzdb that prevents this.)
America/Sao_Paulo:
Period Start (Local) End (Local) Abbrv. Name Bias
Daylight 2019-01-01 00:00:00.000 2019-02-16 22:59:59.000 GMT-02 -02 -2h0m
Ambiguous 2019-02-16 23:00:00.000 2019-02-16 23:59:59.000 -2h0m
Standard 2019-02-17 00:00:00.000 2019-12-31 23:59:59.998 GMT-03 -03 -3h0m
If the previous year has no rules, nothing is brought forward and the start of the year has no carried rule. This results in missing segments.
Same for a period that has no rules at all.
Invalid millisecond values in TDateTime manipulated in FPC. Might require some rounding.
In case of Cairo 2014, the first part of the year has no coverage because there is no "previous year rule" that overlaps this year.
Possible solutions:
Drop TLists and TBucketLists from the code.
Time to move forward.
Hi.
Windows alias translation table (from CLDR project) linked is not latest. It is still 2018i?
Could you please link the latest one?
Thanks
America/Sao_Paulo:
Period Start (Local) End (Local) Abbrv. Name Bias
Daylight 2019-01-01 00:00:00.000 2019-02-16 22:59:59.000 GMT-02 -02 -2h0m
Ambiguous 2019-02-16 23:00:00.000 2019-02-16 23:59:59.000 -2h0m
Standard 2019-02-17 00:00:00.000 2019-12-31 23:59:59.998 GMT-03 -03 -3h0m
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.