From 9e15fadcb930d6781591d14a0fb20e1135bde9c0 Mon Sep 17 00:00:00 2001 From: Stuart Bishop Date: Sun, 20 Mar 2022 11:17:11 +1100 Subject: [PATCH] Squashed 'tz/' changes from d2c79c4bc..e6150f292 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 95ecc37d2 Release 2022a d90452ece * NEWS: Add 2022a "Briefly". 44b73f770 * NEWS: Coalesce Palestine entries. 049044d77 * zdump.c: Fix date typo in comment. e8681e760 Adjust Chile LMT; expand 1946/1947 commentary 0caefb646 Revert "Chile’s Magallanes was like Santiago in 1946/7" 22a2dca72 URL housekeeping 6d6a21f59 Chile’s Magallanes was like Santiago in 1946/7 f4b156691 Palestine springs forward a day later cac76bf92 Fix white space. 318759658 Add URLs to Morocco commentary (thanks to Milamber) 6ff7b3502 Fix French typo 88d2c3909 Fix Lubumbashi between 1897 and 1929 7f60edb1d * private.h (UNINIT_TRAP): Add comment. db9347fbb Fix processing of TZif truncation df4699ddf Add comments on Russia in 1981 (thanks to Alois Treindl) 4117b20d0 Simplify Ukraine metadata 93dcac0c6 Ukraine’s 1992/1996 DST changes 02:00s not 01:00u b74f54452 dumptime’s argument is always nonnull now 3a11c9cc2 I18nize zdump a bit better a12823400 Improve doc for some source files 0b8077257 Simplify recent zdump port 80096e016 zdump ports better to odd C11 platforms b6f92f762 zdump -v reports localtime+gmtime failures better e3c58df90 * Makefile (AWK): Warn re mawk 1.3.3 (thanks to Jonathan Ben Avraham) 9c8cb5d76 No leap second on 2022-06-30 cec7d9e2e Improve rearguard port of post-2087 Morocco 01eeac6b0 zic: omit parens that the C standard doesn’t allow 6cfaa796e Fix "el ds" typo in man pages aa9c4662f * CONTRIBUTING: Move pull request insns to start. 4292b9320 Convert CONTRIBUTING back to plain text b0c24fad4 Rename CONTRIBUTING.md back to CONTRIBUTING 7a200f2b3 Fix Y2242 bug in tzdb tarball generation 5f6467141 Support busybox awk 8407d785a Port zic to Solaris 10 automounts b10ff6d60 Port tzselect to Solaris 10 /bin/sh e4a46da99 Simplify tzselect by omitting old Bash workaround ee44afb40 Distribute tarballs in ustar rather than gnu form 68b99887d Remove duplicate Trinidad and Tobago comment f6c9f51fa Fix minor formatting inconsistencies 3fdd3c482 Rename CONTRIBUTING to CONTRIBUTING.md b0de1570e Switch to Markdown format 228a93f75 Remove bad backzone link for US Virgin Is 8b409e22d Be more generous when dealing with v1 data e5a4add00 Fix uninitialized variable bug 1a4a7eab6 spelling fix 0b13c6b41 Update Palestine commentary 59467e337 Improve Palestine predictions for 2025 and later b102002e5 Release 2021e d86edaf12 Palestine falls back October 29 01:00. 8da2e33e0 Palestine falls back October 28 24:00 4de3d7f24 Release 2021d 951b4f301 * NEWS: Reformat to fit in fewer columns. 5f06f9a31 zic -r now uses -00 for unspecified timestamps f8c660ce6 Simplify zic writezone slightly bdeb83438 Document that -00 means local time is unspecified f74940d96 Fiji suspends DST for the 2021/2022 season 0bf5a761f Fix zic.8 typos 868ba546b Correct spelling of "Treindl" (thanks to Steffen Nurpmeso) e5d72c0f9 Clarify comments re Rome in April 1944 git-subtree-dir: tz git-subtree-split: e6150f292f19c33ae136f70464d6075c41a1a5f3 --- CONTRIBUTING | 66 ++++++++++++----------- Makefile | 13 +++-- NEWS | 91 ++++++++++++++++++++++++++++++- africa | 4 ++ asia | 26 ++++++--- australasia | 24 +++++++-- backzone | 16 ++++-- date.1 | 2 +- europe | 69 +++++++++++++++++++----- leap-seconds.list | 8 +-- localtime.c | 135 +++++++++++++++++++++++++++++----------------- newctime.3 | 2 +- newstrftime.3 | 2 +- newtzset.3 | 2 +- northamerica | 6 +-- private.h | 6 +++ southamerica | 47 ++++++++++++---- theory.html | 27 +++++++--- time2posix.3 | 2 +- tz-link.html | 35 +++++------- tzfile.5 | 6 ++- tzselect.8 | 2 +- tzselect.ksh | 21 +++----- zdump.8 | 2 +- zdump.c | 48 ++++++++++++++--- zic.8 | 13 +++-- zic.c | 39 ++++++++------ ziguard.awk | 8 ++- 28 files changed, 511 insertions(+), 211 deletions(-) diff --git a/CONTRIBUTING b/CONTRIBUTING index 5373354..4c0f56a 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -1,53 +1,58 @@ -Contributing to the tz code and data +# Contributing to the tz code and data + +Please do not create issues or pull requests on GitHub, as the +proper procedure for proposing and distributing patches is via +email as described below. The time zone database is by no means authoritative: governments change timekeeping rules erratically and sometimes with little warning, the data entries do not cover all of civil time before 1970, and undoubtedly errors remain in the code and data. Feel free to fill gaps or fix mistakes, and please email improvements -to tz@iana.org for use in the future. In your email, please give +to for use in the future. In your email, please give reliable sources that reviewers can check. ------ - -Developers can contribute technical changes to the source code and -data as follows. +## Contributing technical changes To email small changes, please run a POSIX shell command like 'diff -u old/europe new/europe >myfix.patch', and attach -myfix.patch to the email. +'myfix.patch' to the email. For more-elaborate or possibly-controversial changes, such as renaming, adding or removing zones, please read - or the file -theory.html. It is also good to browse the mailing list archives +"Theory and pragmatics of the tz code and data" +. +It is also good to browse the mailing list archives for examples of patches that tend to work well. Additions to data should contain commentary citing -reliable sources as justification. Citations should use https: URLs +reliable sources as justification. Citations should use "https:" URLs if available. For changes that fix sensitive security-related bugs, please see the -file SECURITY. +distribution's 'SECURITY' file. -Please submit changes against either the latest release in +Please submit changes against either the latest release or the main branch of the development -repository. The latter is preferred. If you use Git the following -workflow may be helpful: +repository. The latter is preferred. + +## Sample Git workflow for developing contributions + +If you use Git the following workflow may be helpful: * Copy the development repository. - git clone https://github.com/eggert/tz.git - cd tz + git clone https://github.com/eggert/tz.git + cd tz * Get current with the main branch. - git checkout main - git pull + git checkout main + git pull * Switch to a new branch for the changes. Choose a different branch name for each change set. - git checkout -b mybranch + git checkout -b mybranch * Sleuth by using 'git blame'. For example, when fixing data for Africa/Sao_Tome, if the command 'git blame africa' outputs a line @@ -60,36 +65,33 @@ workflow may be helpful: * Debug the changes, e.g.: - make check - make install - ./zdump -v America/Los_Angeles + make check + make install + ./zdump -v America/Los_Angeles * For each separable change, commit it in the new branch, e.g.: - git add northamerica - git commit + git add northamerica + git commit See recent 'git log' output for the commit-message style. - * Create patch files 0001-*, 0002-*, ... + * Create patch files 0001-..., 0002-..., ... - git format-patch main + git format-patch main - * After reviewing the patch files, send the patches to tz@iana.org + * After reviewing the patch files, send the patches to for others to review. - git send-email main + git send-email main For an archived example of such an email, see + "[PROPOSED] Fix off-by-1 error for Jamaica and T&C before 1913" . * Start anew by getting current with the main branch again (the second step above). -Please do not create issues or pull requests on GitHub, as the -proper procedure for proposing and distributing patches is via -email as illustrated above. - ----- This file is in the public domain. diff --git a/Makefile b/Makefile index a222098..a9a989e 100644 --- a/Makefile +++ b/Makefile @@ -399,9 +399,10 @@ ZFLAGS= ZIC_INSTALL= $(ZIC) -d '$(DESTDIR)$(TZDIR)' $(LEAPSECONDS) # The name of a Posix-compliant 'awk' on your system. -# Older 'mawk' versions, such as the 'mawk' in Ubuntu 16.04, might dump core; -# on Ubuntu you can work around this with -# AWK= gawk +# mawk 1.3.3 and Solaris 10 /usr/bin/awk do not work. +# Also, it is better (though not essential) if 'awk' supports UTF-8, +# and unfortunately mawk and busybox awk do not support UTF-8. +# Try AWK=gawk or AWK=nawk if your awk has the abovementioned problems. AWK= awk # The full path name of a Posix-compliant shell, preferably one that supports @@ -466,7 +467,9 @@ OK_LINE= '^'$(OK_CHAR)'*$$' # Flags to give 'tar' when making a distribution. # Try to use flags appropriate for GNU tar. -GNUTARFLAGS= --numeric-owner --owner=0 --group=0 --mode=go+u,go-w --sort=name +GNUTARFLAGS= --format=pax --pax-option='delete=atime,delete=ctime' \ + --numeric-owner --owner=0 --group=0 \ + --mode=go+u,go-w --sort=name TARFLAGS= `if tar $(GNUTARFLAGS) --version >/dev/null 2>&1; \ then echo $(GNUTARFLAGS); \ else :; \ @@ -742,7 +745,7 @@ date: $(DATEOBJS) tzselect: tzselect.ksh version VERSION=`cat version` && sed \ -e 's|#!/bin/bash|#!$(KSHELL)|g' \ - -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ + -e 's|AWK=[^}]*|AWK='\''$(AWK)'\''|g' \ -e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \ -e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \ -e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \ diff --git a/NEWS b/NEWS index f7362c8..ae44be2 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,92 @@ News for the tz database +Release 2022a - 2022-03-15 23:02:01 -0700 + + Briefly: + Palestine will spring forward on 2022-03-27, not -03-26. + zdump -v now outputs better failure indications. + Bug fixes for code that reads corrupted TZif data. + + Changes to future timestamps + + Palestine will spring forward on 2022-03-27, not 2022-03-26. + (Thanks to Heba Hamad.) Predict future transitions for first + Sunday >= March 25. Additionally, predict fallbacks to be the first + Friday on or after October 23, not October's last Friday, to be more + consistent with recent practice. The first differing fallback + prediction is on 2025-10-24, not 2025-10-31. + + Changes to past timestamps + + From 1992 through spring 1996, Ukraine's DST transitions were at + 02:00 standard time, not at 01:00 UTC. (Thanks to Alois Treindl.) + + Chile's Santiago Mean Time and its LMT precursor have been adjusted + eastward by 1 second to align with past and present law. + + Changes to commentary + + Add several references for Chile's 1946/1947 transitions, some of + which only affected portions of the country. + + Changes to code + + Fix bug when mktime gets confused by truncated TZif files with + unspecified local time. (Problem reported by Almaz Mingaleev.) + + Fix bug when 32-bit time_t code reads malformed 64-bit TZif data. + (Problem reported by Christos Zoulas.) + + When reading a version 2 or later TZif file, the TZif reader now + validates the version 1 header and data block only enough to skip + over them, as recommended by RFC 8536 section 4. Also, the TZif + reader no longer mistakenly attempts to parse a version 1 TZIf + file header as a TZ string. + + zdump -v now outputs "(localtime failed)" and "(gmtime failed)" + when local time and UT cannot be determined for a timestamp. + + Changes to build procedure + + Distribution tarballs now use standard POSIX.1-1988 ustar format + instead of GNU format. Although the formats are almost identical + for these tarballs, ustar headers' magic fields contain "ustar" + instead of "ustar ", and their version fields contain "00" instead + of " ". The two formats are planned to diverge more significantly + for tzdb releases after 2242-03-16 12:56:31 UTC, when the ustar + format becomes obsolete and the tarballs switch to pax format, an + extension of ustar. For details about these formats, please see + "pax - portable archive interchange", IEEE Std 1003.1-2017, + . + + +Release 2021e - 2021-10-21 18:41:00 -0700 + + Changes to future timestamps + + Palestine will fall back 10-29 (not 10-30) at 01:00. + (Thanks to P Chan and Heba Hemad.) + + +Release 2021d - 2021-10-15 13:48:18 -0700 + + Briefly: + Fiji suspends DST for the 2021/2022 season. + 'zic -r' marks unspecified timestamps with "-00". + + Changes to future timestamps + + Fiji will suspend observance of DST for the 2021/2022 season. + Assume for now that it will return next year. (Thanks to Jashneel + Kumar and P Chan.) + + Changes to code + + 'zic -r' now uses "-00" time zone abbreviations for intervals + with UT offsets that are unspecified due to -r truncation. + This implements a change in draft Internet RFC 8536bis. + + Release 2021c - 2021-10-01 14:21:49 -0700 Briefly: @@ -546,13 +633,13 @@ Release 2019c - 2019-09-11 08:59:48 -0700 probably wrong.) Fix several errors in pre-1970 transitions in Perry County, IN. - (Thanks to Alois Triendl for pointing out the 1967/9 errors.) + (Thanks to Alois Treindl for pointing out the 1967/9 errors.) Edmonton did not observe DST in 1967 or 1969. In 1946 Vancouver ended DST on 09-29 not 10-13, and Vienna ended DST on 10-07 not 10-06. In 1945 Königsberg (now Kaliningrad) switched from +01/+02 to +02/+03 on 04-10 not 01-01, and its +02/+03 is abbreviated - EET/EEST, not CET/CEST. (Thanks to Alois Triendl.) In 1946 + EET/EEST, not CET/CEST. (Thanks to Alois Treindl.) In 1946 Königsberg switched to +03 on 04-07 not 01-01. In 1946 Louisville switched from CST to CDT on 04-28 at 00:01, not diff --git a/africa b/africa index 48e9d79..4bf491e 100644 --- a/africa +++ b/africa @@ -918,6 +918,10 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis # (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a)) # (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b))))) # (setq islamic-year (+ 1 islamic-year)))) +# +# From Milamber (2021-03-31, 2022-03-10), confirming these predictions: +# https://www.mmsp.gov.ma/fr/actualites.aspx?id=2076 +# https://www.ecoactu.ma/horaires-administration-ramadan-gmtheure-gmt-a-partir-de-dimanche-27-mars/ # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Morocco 1939 only - Sep 12 0:00 1:00 - diff --git a/asia b/asia index 4e95797..049b35c 100644 --- a/asia +++ b/asia @@ -3386,11 +3386,6 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # shall [end] on Oct 24th 2020 at 01:00AM by delaying the clock by 60 minutes. # http://www.palestinecabinet.gov.ps/portal/Meeting/Details/51584 -# From Tim Parenti (2020-10-20): -# Predict future fall transitions at 01:00 on the Saturday preceding October's -# last Sunday (i.e., Sat>=24). This is consistent with our predictions since -# 2016, although the time of the change differed slightly in 2019. - # From Pierre Cashon (2020-10-20): # The summer time this year started on March 28 at 00:00. # https://wafa.ps/ar_page.aspx?id=GveQNZa872839351758aGveQNZ @@ -3403,6 +3398,21 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # For now, guess spring-ahead transitions are at 00:00 on the Saturday # preceding March's last Sunday (i.e., Sat>=24). +# From P Chan (2021-10-18): +# http://wafa.ps/Pages/Details/34701 +# Palestine winter time will start from midnight 2021-10-29 (Thursday-Friday). +# +# From Heba Hemad, Palestine Ministry of Telecom & IT (2021-10-20): +# ... winter time will begin in Palestine from Friday 10-29, 01:00 AM +# by 60 minutes backwards. +# +# From Tim Parenti (2021-10-25), per Paul Eggert (2021-10-24): +# Guess future fall transitions at 01:00 on the Friday preceding October's +# last Sunday (i.e., Fri>=23), as this is more consistent with recent practice. + +# From Heba Hamad (2022-03-10): +# summer time will begin in Palestine from Sunday 03-27-2022, 00:00 AM. + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S Rule EgyptAsia 1957 1958 - Oct 1 0:00 0 - @@ -3437,8 +3447,10 @@ Rule Palestine 2016 2018 - Mar Sat>=24 1:00 1:00 S Rule Palestine 2016 2018 - Oct Sat>=24 1:00 0 - Rule Palestine 2019 only - Mar 29 0:00 1:00 S Rule Palestine 2019 only - Oct Sat>=24 0:00 0 - -Rule Palestine 2020 max - Mar Sat>=24 0:00 1:00 S -Rule Palestine 2020 max - Oct Sat>=24 1:00 0 - +Rule Palestine 2020 2021 - Mar Sat>=24 0:00 1:00 S +Rule Palestine 2020 only - Oct 24 1:00 0 - +Rule Palestine 2021 max - Oct Fri>=23 1:00 0 - +Rule Palestine 2022 max - Mar Sun>=25 0:00 1:00 S # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct diff --git a/australasia b/australasia index 7348b87..77c2c69 100644 --- a/australasia +++ b/australasia @@ -385,9 +385,22 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 # "Minister for Employment, Parveen Bala says they had never thought of # stopping daylight saving. He says it was just to decide on when it should # start and end. Bala says it is a short period..." -# Since the end date is still in line with our ongoing predictions, assume for -# now that the later-than-usual start date is a one-time departure from the -# recent second Sunday in November pattern. +# +# From Tim Parenti (2021-10-11), per Jashneel Kumar (2021-10-11) and P Chan +# (2021-10-12): +# https://www.fiji.gov.fj/Media-Centre/Speeches/English/PM-BAINIMARAMA-S-COVID-19-ANNOUNCEMENT-10-10-21 +# https://www.fbcnews.com.fj/news/covid-19/curfew-moved-back-to-11pm/ +# In a 2021-10-10 speech concerning updated Covid-19 mitigation measures in +# Fiji, prime minister Josaia Voreqe "Frank" Bainimarama announced the +# suspension of DST for the 2021/2022 season: "Given that we are in the process +# of readjusting in the midst of so many changes, we will also put Daylight +# Savings Time on hold for this year. It will also make the reopening of +# scheduled commercial air service much smoother if we don't have to be +# concerned shifting arrival and departure times, which may look like a simple +# thing but requires some significant logistical adjustments domestically and +# internationally." +# Assume for now that DST will resume with the recent pre-2020 rules for the +# 2022/2023 season. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 - @@ -399,10 +412,11 @@ Rule Fiji 2011 only - Mar Sun>=1 3:00 0 - Rule Fiji 2012 2013 - Jan Sun>=18 3:00 0 - Rule Fiji 2014 only - Jan Sun>=18 2:00 0 - Rule Fiji 2014 2018 - Nov Sun>=1 2:00 1:00 - -Rule Fiji 2015 max - Jan Sun>=12 3:00 0 - +Rule Fiji 2015 2021 - Jan Sun>=12 3:00 0 - Rule Fiji 2019 only - Nov Sun>=8 2:00 1:00 - Rule Fiji 2020 only - Dec 20 2:00 1:00 - -Rule Fiji 2021 max - Nov Sun>=8 2:00 1:00 - +Rule Fiji 2022 max - Nov Sun>=8 2:00 1:00 - +Rule Fiji 2023 max - Jan Sun>=12 3:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva 12:00 Fiji +12/+13 diff --git a/backzone b/backzone index 9b51273..879a140 100644 --- a/backzone +++ b/backzone @@ -290,6 +290,7 @@ Rule SL 1932 only - Dec 1 0:00 0:20 -0040 Rule SL 1933 1938 - Mar 31 24:00 0 -01 Rule SL 1933 1939 - Aug 31 24:00 0:20 -0040 Rule SL 1939 only - May 31 24:00 0 -01 + Zone Africa/Freetown -0:53:00 - LMT 1882 -0:53:00 - FMT 1913 Jul 1 # Freetown MT -1:00 SL %s 1939 Sep 5 @@ -345,7 +346,15 @@ Zone Africa/Luanda 0:52:56 - LMT 1892 1:00 - WAT # Democratic Republic of the Congo (east) -Zone Africa/Lubumbashi 1:49:52 - LMT 1897 Nov 9 +# +# From Alois Treindl (2022-02-28): +# My main source for its time zone history is +# Henri le Corre, Régimes horaires pour l'Europe et l'Afrique. +# Shanks follows le Corre. As does Françoise Schneider-Gauquelin in her book +# Problèmes de l'heure résolus pour le monde entier. +# +Zone Africa/Lubumbashi 1:49:52 - LMT 1897 Nov 9 + 1:00 - WAT 1920 Apr 25 2:00 - CAT # Zambia @@ -752,7 +761,6 @@ Zone America/Port_of_Spain -4:06:04 - LMT 1912 Mar 2 -4:00 - AST Link America/Port_of_Spain America/Marigot Link America/Port_of_Spain America/St_Barthelemy -Link America/Port_of_Spain America/Virgin # Argentina # This entry was intended for the following areas, but has been superseded by @@ -815,11 +823,11 @@ Link Antarctica/McMurdo Antarctica/South_Pole # Syowa station, which is the first antarctic station of Japan, # was established on 1957-01-29. Since Syowa station is still the main # station of Japan, it's appropriate for the principal location. -Zone Antarctica/Syowa 0 - -00 1957 Jan 29 - 3:00 - +03 # See: # NIPR Antarctic Research Activities (1999-08-17) # http://www.nipr.ac.jp/english/ara01.html +Zone Antarctica/Syowa 0 - -00 1957 Jan 29 + 3:00 - +03 # Yemen # Milne says 2:59:54 was the meridian of the saluting battery at Aden, diff --git a/date.1 b/date.1 index 432cab1..1ecd63a 100644 --- a/date.1 +++ b/date.1 @@ -5,7 +5,7 @@ date \- show and set date and time .if n .nh .if n .na .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- .B date [ .B \*-u diff --git a/europe b/europe index 2adc308..208585d 100644 --- a/europe +++ b/europe @@ -821,7 +821,7 @@ Zone Europe/Andorra 0:06:04 - LMT 1901 # Shanks & Pottenger give 02:00, the BEV 00:00. Go with the BEV, # and guess 02:00 for 1945-04-12. -# From Alois Triendl (2019-07-22): +# From Alois Treindl (2019-07-22): # In 1946 the end of DST was on Monday, 7 October 1946, at 3:00 am. # Shanks had this right. Source: Die Weltpresse, 5. Oktober 1946, page 5. @@ -1735,19 +1735,22 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908 # advanced to sixty minutes later starting at hour two on 1944-04-02; ... # Starting at hour three on the date 1944-09-17 standard time will be resumed. # -# From Alois Triendl (2019-07-02): +# From Alois Treindl (2019-07-02): # I spent 6 Euros to buy two archive copies of Il Messaggero, a Roman paper, # for 1 and 2 April 1944. The edition of 2 April has this note: "Tonight at 2 # am, put forward the clock by one hour. Remember that in the night between # today and Monday the 'ora legale' will come in force again." That makes it # clear that in Rome the change was on Monday, 3 April 1944 at 2 am. # -# From Paul Eggert (2016-10-27): +# From Paul Eggert (2021-10-05): # Go with INRiM for DST rules, except as corrected by Inglis for 1944 # for the Kingdom of Italy. This is consistent with Renzo Baldini. # Model Rome's occupation by using C-Eur rules from 1943-09-10 # to 1944-06-04; although Rome was an open city during this period, it -# was effectively controlled by Germany. +# was effectively controlled by Germany. Using C-Eur is consistent +# with Treindl's comment about Rome in April 1944, as the "Rule Italy" +# lines during German occupation do not affect Europe/Rome +# (though they do affect Europe/Malta). # # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Italy 1916 only - Jun 3 24:00 1:00 S @@ -2623,7 +2626,7 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct # Although Shanks lists 1945-01-01 as the date for transition from # +01/+02 to +02/+03, more likely this is a placeholder. Guess that # the transition occurred at 1945-04-10 00:00, which is about when -# Königsberg surrendered to Soviet troops. (Thanks to Alois Triendl.) +# Königsberg surrendered to Soviet troops. (Thanks to Alois Treindl.) # From Paul Eggert (2016-03-18): # The 1989 transition is from USSR act No. 227 (1989-03-14). @@ -2782,8 +2785,26 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr # says he remembers that Samara opted out of the 1992-01-19 exception # 2 days before the switch. # -# -# From Paul Eggert (2016-03-18): +# From Alois Treindl (2022-02-15): +# the Russian wikipedia page +# https://ru.wikipedia.org/wiki/Московское_время#Перемещение_границы_применения_московского_времени_на_восток +# contains the sentence (in Google translation) "In the autumn of +# 1981, Arkhangelsk, Vologda, Yaroslavl, Ivanovo, Vladimir, Ryazan, +# Lipetsk, Voronezh, Rostov-on-Don, Krasnodar and regions to the east +# of those named (about 30 in total) parted ways with Moscow time. +# However, the convenience of common time with Moscow turned out to be +# decisive - in 1982, these regions again switched to Moscow time." +# Shanks International atlas has similar information, and also the +# Russian book Zaitsev A., Kutalev D. A new astrologer's reference +# book. Coordinates of cities and time corrections, - The World of +# Urania, 2012 (Russian: Зайцев А., Куталёв Д., Новый справочник +# астролога. Координаты городов и временные поправки). +# To me it seems that an extra zone is needed, which starts with LMT +# util 1919, later follows Moscow since 1930, but deviates from it +# between 1 October 1981 until 1 April 1982. +# +# +# From Paul Eggert (2022-02-15): # Given the above, we appear to be missing some Zone entries for the # chaotic early 1980s in Russia. It's not clear what these entries # should be. For now, sweep this under the rug and just document the @@ -2830,7 +2851,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 1:00 C-Eur CE%sT 1944 Apr 13 3:00 Russia MSK/MSD 1990 3:00 - MSK 1990 Jul 1 2:00 - 2:00 - EET 1992 + 2:00 - EET 1992 Mar 20 # Central Crimea used Moscow time 1994/1997. # # From Paul Eggert (2006-03-22): @@ -2840,7 +2861,7 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 # sometime between the 1994 DST switches. Shanks & Pottenger simply say # 1994-09-25 03:00, but that can't be right. For now, guess it # changed in May. - 2:00 E-Eur EE%sT 1994 May + 2:00 C-Eur EE%sT 1994 May # From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev. 3:00 E-Eur MSK/MSD 1996 Mar 31 0:00s 3:00 1:00 MSD 1996 Oct 27 3:00s @@ -4007,6 +4028,27 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents. # Ukraine # +# From Alois Triendl (2014-03-01): +# REGULATION A N O V A on March 20, 1992 N 139 ... means that from +# 1992 on, Ukraine had DST with begin time at 02:00 am, on last Sunday +# in March, and end time 03:00 am, last Sunday in September.... +# CABINET OF MINISTERS OF UKRAINE RESOLUTION on May 13, 1996 N 509 +# "On the order of computation time on the territory of Ukraine" .... +# As this cabinet decision is from May 1996, it seems likely that the +# transition in March 1996, which predates it, was still at 2:00 am +# and not at 3:00 as would have been under EU rules. +# This is why I have set the change to EU rules into May 1996, +# so that the change in March is stil covered by the Ukraine rule. +# The next change in October 1996 happened under EU rules.... +# TZ database holds three other zones for Ukraine.... I have not yet +# worked out the consequences for these three zones, as we (me and my +# US colleague David Cochrane) are still trying to get more +# information upon these local deviations from Kiev rules. +# +# From Paul Eggert (2022-02-08): +# For now, assume that Ukraine's other three zones followed the same rules, +# except that Crimea switched to Moscow time in 1994 as described elsewhere. + # From Igor Karpov, who works for the Ukrainian Ministry of Justice, # via Garrett Wollman (2003-01-27): # BTW, I've found the official document on this matter. It's government @@ -4096,7 +4138,7 @@ Zone Europe/Kiev 2:02:04 - LMT 1880 1:00 C-Eur CE%sT 1943 Nov 6 3:00 Russia MSK/MSD 1990 Jul 1 2:00 2:00 1:00 EEST 1991 Sep 29 3:00 - 2:00 E-Eur EE%sT 1995 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Transcarpathia used CET 1990/1991. # "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but @@ -4109,8 +4151,8 @@ Zone Europe/Uzhgorod 1:29:12 - LMT 1890 Oct 3:00 Russia MSK/MSD 1990 3:00 - MSK 1990 Jul 1 2:00 1:00 - CET 1991 Mar 31 3:00 - 2:00 - EET 1992 - 2:00 E-Eur EE%sT 1995 + 2:00 - EET 1992 Mar 20 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991. # "Zaporizhia" is the transliteration of the Ukrainian name, but @@ -4123,7 +4165,8 @@ Zone Europe/Zaporozhye 2:20:40 - LMT 1880 3:00 - MSK 1941 Aug 25 1:00 C-Eur CE%sT 1943 Oct 25 3:00 Russia MSK/MSD 1991 Mar 31 2:00 - 2:00 E-Eur EE%sT 1995 + 2:00 E-Eur EE%sT 1992 Mar 20 + 2:00 C-Eur EE%sT 1996 May 13 2:00 EU EE%sT # Vatican City diff --git a/leap-seconds.list b/leap-seconds.list index cfda3e8..0f43115 100644 --- a/leap-seconds.list +++ b/leap-seconds.list @@ -204,10 +204,10 @@ # current -- the update time stamp, the data and the name of the file # will not change. # -# Updated through IERS Bulletin C62 -# File expires on: 28 June 2022 +# Updated through IERS Bulletin C63 +# File expires on: 28 December 2022 # -#@ 3865363200 +#@ 3881174400 # 2272060800 10 # 1 Jan 1972 2287785600 11 # 1 Jul 1972 @@ -252,4 +252,4 @@ # the hash line is also ignored in the # computation. # -#h 599d45bf accd4b4f 8b60e46 49b623 7d13b825 +#h 732b2044 5863a938 b7e43179 1339c710 ded63837 diff --git a/localtime.c b/localtime.c index 6a687d7..913c7e8 100644 --- a/localtime.c +++ b/localtime.c @@ -105,6 +105,15 @@ struct lsinfo { /* leap second information */ #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b)) #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) +/* This abbreviation means local time is unspecified. */ +static char const UNSPEC[] = "-00"; + +/* How many extra bytes are needed at the end of struct state's chars array. + This needs to be at least 1 for null termination in case the input + data isn't properly terminated, and it also needs to be big enough + for ttunspecified to work without crashing. */ +enum { CHARS_EXTRA = BIGGEST(sizeof UNSPEC, 2) - 1 }; + #ifdef TZNAME_MAX #define MY_TZNAME_MAX TZNAME_MAX #endif /* defined TZNAME_MAX */ @@ -122,7 +131,8 @@ struct state { time_t ats[TZ_MAX_TIMES]; unsigned char types[TZ_MAX_TIMES]; struct ttinfo ttis[TZ_MAX_TYPES]; - char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), + char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + CHARS_EXTRA, + sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))]; struct lsinfo lsis[TZ_MAX_LEAPS]; @@ -211,6 +221,15 @@ init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx) s->tt_ttisut = false; } +/* Return true if SP's time type I does not specify local time. */ +static bool +ttunspecified(struct state const *sp, int i) +{ + char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx]; + /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA. */ + return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0; +} + static int_fast32_t detzcode(const char *const codep) { @@ -434,35 +453,45 @@ tzloadbody(char const *name, struct state *sp, bool doextend, if (close(fid) < 0) return errno; for (stored = 4; stored <= 8; stored *= 2) { - int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt); - int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt); - int_fast64_t prevtr = -1; - int_fast32_t prevcorr; - int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt); - int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt); - int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt); - int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt); - char const *p = up->buf + tzheadsize; - /* Although tzfile(5) currently requires typecnt to be nonzero, - support future formats that may allow zero typecnt - in files that have a TZ string and no transitions. */ - if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS - && 0 <= typecnt && typecnt < TZ_MAX_TYPES - && 0 <= timecnt && timecnt < TZ_MAX_TIMES - && 0 <= charcnt && charcnt < TZ_MAX_CHARS - && (ttisstdcnt == typecnt || ttisstdcnt == 0) - && (ttisutcnt == typecnt || ttisutcnt == 0))) - return EINVAL; - if (nread - < (tzheadsize /* struct tzhead */ - + timecnt * stored /* ats */ + char version = up->tzhead.tzh_version[0]; + bool skip_datablock = stored == 4 && version; + int_fast32_t datablock_size; + int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt); + int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt); + int_fast64_t prevtr = -1; + int_fast32_t prevcorr; + int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt); + int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt); + int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt); + int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt); + char const *p = up->buf + tzheadsize; + /* Although tzfile(5) currently requires typecnt to be nonzero, + support future formats that may allow zero typecnt + in files that have a TZ string and no transitions. */ + if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS + && 0 <= typecnt && typecnt < TZ_MAX_TYPES + && 0 <= timecnt && timecnt < TZ_MAX_TIMES + && 0 <= charcnt && charcnt < TZ_MAX_CHARS + && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES + && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES)) + return EINVAL; + datablock_size + = (timecnt * stored /* ats */ + timecnt /* types */ + typecnt * 6 /* ttinfos */ + charcnt /* chars */ + leapcnt * (stored + 4) /* lsinfos */ + ttisstdcnt /* ttisstds */ - + ttisutcnt)) /* ttisuts */ + + ttisutcnt); /* ttisuts */ + if (nread < tzheadsize + datablock_size) + return EINVAL; + if (skip_datablock) + p += datablock_size; + else { + if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0) + && (ttisutcnt == typecnt || ttisutcnt == 0))) return EINVAL; + sp->leapcnt = leapcnt; sp->timecnt = timecnt; sp->typecnt = typecnt; @@ -518,7 +547,9 @@ tzloadbody(char const *name, struct state *sp, bool doextend, } for (i = 0; i < sp->charcnt; ++i) sp->chars[i] = *p++; - sp->chars[i] = '\0'; /* ensure '\0' at end */ + /* Ensure '\0'-terminated, and make it safe to call + ttunspecified later. */ + memset(&sp->chars[i], 0, CHARS_EXTRA); /* Read leap seconds, discarding those out of time_t range. */ leapcnt = 0; @@ -526,24 +557,29 @@ tzloadbody(char const *name, struct state *sp, bool doextend, int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p); int_fast32_t corr = detzcode(p + stored); p += stored + 4; + /* Leap seconds cannot occur before the Epoch, or out of order. */ if (tr <= prevtr) return EINVAL; + + /* To avoid other botches in this code, each leap second's + correction must differ from the previous one's by 1 + second or less, except that the first correction can be + any value; these requirements are more generous than + RFC 8536, to allow future RFC extensions. */ + if (! (i == 0 + || (prevcorr < corr + ? corr == prevcorr + 1 + : (corr == prevcorr + || corr == prevcorr - 1)))) + return EINVAL; + prevtr = tr; + prevcorr = corr; + if (tr <= TIME_T_MAX) { - /* To avoid other botches in this code, each leap second's - correction must differ from the previous one's by 1 - second or less, except that the first correction can be - any value; these requirements are more generous than - RFC 8536, to allow future RFC extensions. */ - if (! (i == 0 - || (prevcorr < corr - ? corr == prevcorr + 1 - : (corr == prevcorr - || corr == prevcorr - 1)))) - return EINVAL; - sp->lsis[leapcnt].ls_trans = prevtr = tr; - sp->lsis[leapcnt].ls_corr = prevcorr = corr; + sp->lsis[leapcnt].ls_trans = tr; + sp->lsis[leapcnt].ls_corr = corr; leapcnt++; } } @@ -573,13 +609,14 @@ tzloadbody(char const *name, struct state *sp, bool doextend, ttisp->tt_ttisut = *p++; } } - /* - ** If this is an old file, we're done. - */ - if (up->tzhead.tzh_version[0] == '\0') - break; - nread -= p - up->buf; - memmove(up->buf, p, nread); + } + + nread -= p - up->buf; + memmove(up->buf, p, nread); + + /* If this is an old file, we're done. */ + if (!version) + break; } if (doextend && nread > 2 && up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && @@ -682,13 +719,13 @@ tzloadbody(char const *name, struct state *sp, bool doextend, standard-time type. See: https://mm.icann.org/pipermail/tz/2013-May/019368.html */ /* - ** If type 0 is unused in transitions, + ** If type 0 does not specify local time, or is unused in transitions, ** it's the type to use for early times. */ for (i = 0; i < sp->timecnt; ++i) if (sp->types[i] == 0) break; - i = i < sp->timecnt ? -1 : 0; + i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0; /* ** Absent the above, ** if there are transition times @@ -2073,6 +2110,8 @@ time2sub(struct tm *const tmp, for (j = sp->typecnt - 1; j >= 0; --j) { if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) continue; + if (ttunspecified(sp, j)) + continue; newt = (t + sp->ttis[j].tt_utoff - sp->ttis[i].tt_utoff); if (! funcp(sp, &newt, offset, &mytm)) @@ -2165,7 +2204,7 @@ time1(struct tm *const tmp, seen[i] = false; nseen = 0; for (i = sp->timecnt - 1; i >= 0; --i) - if (!seen[sp->types[i]]) { + if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) { seen[sp->types[i]] = true; types[nseen++] = sp->types[i]; } diff --git a/newctime.3 b/newctime.3 index cc56e2c..1b1790f 100644 --- a/newctime.3 +++ b/newctime.3 @@ -4,7 +4,7 @@ asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time .SH SYNOPSIS .nf .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- .B #include .PP .BR "extern char *tzname[];" " /\(** (optional) \(**/" diff --git a/newstrftime.3 b/newstrftime.3 index 887aba5..d68bc33 100644 --- a/newstrftime.3 +++ b/newstrftime.3 @@ -41,7 +41,7 @@ strftime \- format date and time .SH SYNOPSIS .nf .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- .B #include .PP .B "size_t strftime(char *restrict buf, size_t maxsize," diff --git a/newtzset.3 b/newtzset.3 index 05aa350..8aaa0ff 100644 --- a/newtzset.3 +++ b/newtzset.3 @@ -4,7 +4,7 @@ tzset \- initialize time conversion information .SH SYNOPSIS .nf .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- .B #include .PP .B timezone_t tzalloc(char const *TZ); diff --git a/northamerica b/northamerica index b1a306d..fb5c94b 100644 --- a/northamerica +++ b/northamerica @@ -976,7 +976,7 @@ Zone America/Indiana/Vincennes -5:50:07 - LMT 1883 Nov 18 12:09:53 -5:00 US E%sT # # Perry County, Indiana, switched from eastern to central time in April 2006. -# From Alois Triendl (2019-07-09): +# From Alois Treindl (2019-07-09): # The Indianapolis News, Friday 27 October 1967 states that Perry County # returned to CST. It went again to EST on 27 April 1969, as documented by the # Indianapolis star of Saturday 26 April. @@ -1936,7 +1936,7 @@ Zone America/Swift_Current -7:11:20 - LMT 1905 Sep # Alberta -# From Alois Triendl (2019-07-19): +# From Alois Treindl (2019-07-19): # There was no DST in Alberta in 1967... Calgary Herald, 29 April 1967. # 1969, no DST, from Edmonton Journal 18 April 1969 # @@ -1991,7 +1991,7 @@ Zone America/Edmonton -7:33:52 - LMT 1906 Sep # # From Paul Eggert (2019-07-25): # Shanks says Fort Nelson did not observe DST in 1946, unlike Vancouver. -# Alois Triendl confirmed this on 07-22, citing the 1946-04-27 Vancouver Daily +# Alois Treindl confirmed this on 07-22, citing the 1946-04-27 Vancouver Daily # Province. He also cited the 1946-09-28 Victoria Daily Times, which said # that Vancouver, Victoria, etc. "change at midnight Saturday"; for now, # guess they meant 02:00 Sunday since 02:00 was common practice in Vancouver. diff --git a/private.h b/private.h index 4c03324..e8c0942 100644 --- a/private.h +++ b/private.h @@ -689,6 +689,12 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE; # define INITIALIZE(x) #endif +/* Whether memory access must strictly follow the C standard. + If 0, it's OK to read uninitialized storage so long as the value is + not relied upon. Defining it to 0 lets mktime access parts of + struct tm that might be uninitialized, as a heuristic when the + standard doesn't say what to return and when tm_gmtoff can help + mktime likely infer a better value. */ #ifndef UNINIT_TRAP # define UNINIT_TRAP 0 #endif diff --git a/southamerica b/southamerica index 7900af9..c6249cd 100644 --- a/southamerica +++ b/southamerica @@ -1086,7 +1086,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # Chile -# From Paul Eggert (2015-04-03): +# From Paul Eggert (2022-03-15): # Shanks & Pottenger says America/Santiago introduced standard time in # 1890 and rounds its UT offset to 70W40; guess that in practice this # was the same offset as in 1916-1919. It also says Pacific/Easter @@ -1109,7 +1109,7 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # Historia de la hora oficial de Chile (retrieved 2012-10-24). See: # https://web.archive.org/web/20121024234627/http://www.horaoficial.cl/horaof.htm # A fancier Spanish version (requiring mouse-clicking) is at: -# http://www.horaoficial.cl/historia_hora.html +# http://www.horaoficial.cl/historia_hora.php # Conflicts between [1] and [2] were resolved as follows: # # - [1] says the 1910 transition was Jan 1, [2] says Jan 10 and cites @@ -1118,7 +1118,8 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # - [1] says SMT was -4:42:45, [2] says Chile's official time from # 1916 to 1919 was -4:42:46.3, the meridian of Chile's National # Astronomical Observatory (OAN), then located in what is now -# Quinta Normal in Santiago. Go with [2], rounding it to -4:42:46. +# Quinta Normal in Santiago. Go with [1], as this matches the meridian +# referred to by the relevant Chilean laws to this day. # # - [1] says the 1918 transition was Sep 1, [2] says Sep 10 and cites # Boletín No. 22, Aviso No. 129/1918 (1918-08-23). Go with [2]. @@ -1140,6 +1141,32 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # this is known to work for DST transitions starting in 2008 and # may well be true for earlier transitions. +# From Tim Parenti (2022-03-15): +# For a brief period of roughly six weeks in 1946, DST was only observed on an +# emergency basis in specific regions of central Chile; namely, "the national +# territory between the provinces of Coquimbo and Concepción, inclusive". +# This was enacted by Decree 3,891, dated 1946-07-13, and took effect +# 1946-07-14 24:00, advancing these central regions to -03. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460715/#page/1 +# The decree contemplated "[t]hat this advancement of the Official Time, even +# though it has been proposed for the cities of Santiago and Valparaíso only, +# must be agreed with that of other cities, due to the connection of various +# activities that require it, such as, for example, the operation of rail +# services". It was originally set to expire after 30 days but was extended +# through 1946-08-31 by Decree 4,506, dated 1946-08-13. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460814/#page/1 +# +# Law Number 8,522, promulgated 1946-08-27, reunified Chilean clocks at their +# new "Summer Time" of -04, reckoned as that of "the meridian of the +# Astronomical Observatory of Lo Espejo, advanced by 42 minutes and 45 +# seconds". +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19460828/#page/1 +# After a brief "Winter Time" stint at -05 beginning 1947-04-01, Law Number +# 8,777, promulgated 1947-05-17, established year-round -04 "from 23:00 on the +# second day after it is published in the 'Diario Oficial'." It was published +# on Monday 1947-05-19 and so took effect from Wednesday 1947-05-21 23:00. +# https://www.diariooficial.interior.gob.cl/versiones-anteriores/do-h/19470519/#page/1 + # From Eduardo Krell (1995-10-19): # The law says to switch to DST at midnight [24:00] on the second SATURDAY # of October.... The law is the same for March and October. @@ -1298,12 +1325,12 @@ Rule Chile 2019 max - Sep Sun>=2 4:00u 1:00 - # IATA SSIM anomalies: (1992-02) says 1992-03-14; # (1996-09) says 1998-03-08. Ignore these. # Zone NAME STDOFF RULES FORMAT [UNTIL] -Zone America/Santiago -4:42:46 - LMT 1890 - -4:42:46 - SMT 1910 Jan 10 # Santiago Mean Time +Zone America/Santiago -4:42:45 - LMT 1890 + -4:42:45 - SMT 1910 Jan 10 # Santiago Mean Time -5:00 - -05 1916 Jul 1 - -4:42:46 - SMT 1918 Sep 10 + -4:42:45 - SMT 1918 Sep 10 -4:00 - -04 1919 Jul 1 - -4:42:46 - SMT 1927 Sep 1 + -4:42:45 - SMT 1927 Sep 1 -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 @@ -1313,11 +1340,11 @@ Zone America/Santiago -4:42:46 - LMT 1890 -5:00 - -05 1947 May 21 23:00 -4:00 Chile -04/-03 Zone America/Punta_Arenas -4:43:40 - LMT 1890 - -4:42:46 - SMT 1910 Jan 10 + -4:42:45 - SMT 1910 Jan 10 -5:00 - -05 1916 Jul 1 - -4:42:46 - SMT 1918 Sep 10 + -4:42:45 - SMT 1918 Sep 10 -4:00 - -04 1919 Jul 1 - -4:42:46 - SMT 1927 Sep 1 + -4:42:45 - SMT 1927 Sep 1 -5:00 Chile -05/-04 1932 Sep 1 -4:00 - -04 1942 Jun 1 -5:00 - -05 1942 Aug 1 diff --git a/theory.html b/theory.html index 5a05f4b..28cc88e 100644 --- a/theory.html +++ b/theory.html @@ -296,7 +296,7 @@

Timezone identifiers

  • If a name is changed, put its old spelling in the - 'backward' file. + 'backward' file as a link to the new spelling. This means old spellings will continue to work. Ordinarily a name change should occur only in the rare case when a location's consensus English-language spelling changes; for example, @@ -348,22 +348,37 @@

    Timezone identifiers

    -The file 'zone1970.tab' lists geographical locations used +The file zone1970.tab lists geographical locations used to name timezones. It is intended to be an exhaustive list of names for geographic regions as described above; this is a subset of the timezones in the data. -Although a 'zone1970.tab' location's +Although a zone1970.tab location's longitude corresponds to its local mean time (LMT) offset with one hour for every 15° east longitude, this relationship is not exact. +The backward-compatibility file zone.tab is similar +but conforms to the older-version guidelines related to ISO 3166-1; +it lists only one country code per entry and unlike zone1970.tab +it can list names defined in backward.

    -Excluding 'backward' should not affect the other data. -If 'backward' is excluded, excluding -'etcetera' should not affect the remaining data. +The database defines each timezone name to be a zone, or a link to a zone. +The source file backward defines links for backward +compatibility; it does not define zones. +Although backward was originally designed to be optional, +nowadays distributions typically use it +and no great weight should be attached to whether a link +is defined in backward or in some other file. +The source file etcetera defines names that may be useful +on platforms that do not support POSIX-style TZ strings; +no other source file other than backward +contains links to its zones. +One of etcetera's names is GMT, +used by functions like gmtime to obtain leap +second information on platforms that support leap seconds.

    diff --git a/time2posix.3 b/time2posix.3 index fbb5766..2ea7edc 100644 --- a/time2posix.3 +++ b/time2posix.3 @@ -4,7 +4,7 @@ time2posix, posix2time \- convert seconds since the Epoch .SH SYNOPSIS .nf .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- .B #include .PP .B time_t time2posix(time_t t); diff --git a/tz-link.html b/tz-link.html index d2661ad..92da48f 100644 --- a/tz-link.html +++ b/tz-link.html @@ -89,7 +89,6 @@

    The tz database

    title="Web Operating System">webOS, AIX, -BlackBerry 10, iOS, macOS, @@ -243,18 +242,18 @@

    Changes to the tz database

    the tz README file and installing the latest data yourself. System-specific instructions for installing the latest tz data have also been published -for AIX, +for AIX, Android, ICU, -IBM +IBM JDK, Joda-Time, MySQL, Noda Time, and OpenJDK/Oracle JDK. +href="https://www.oracle.com/java/technologies/javase/tzupdater-readme.html">OpenJDK/Oracle JDK.

    Sources for the tz database are Other tz compilers href="https://github.com/formatjs/date-time-format-timezone">Intl.DateTimeFormat timezone polyfill is freely available under a BSD-style license.

  • -
  • CompactTimeZoneGenerator -compiles time zone data into a compact form designed for -JavaScript. It is freely available under a combination of -the MIT license and the Apache License.
  • The date-fns library manipulates timezone-aware timestamps in browsers and in Node.js. @@ -546,9 +540,9 @@

    Other tz compilers

    Definitions for Python compiles tz source into Python. It is freely available under a BSD-style license. -In code that can assume Python 3.9 or later it is superseded by -zoneinfo.ZoneInfo -and the tzdata Python package.
  • +In code that can assume Python 3.6 or later it is largely superseded; see pytz: +The Fastest Footgun in the West.
  • TZInfo – Ruby Timezone Library compiles tz source into @@ -610,11 +604,11 @@

    Other TZif readers

    It is freely available under the same terms as Perl (dual GPL and Artistic license).
  • Python has a zoneinfo.ZoneInfo +href="https://docs.python.org/3/library/zoneinfo.html">zoneinfo.ZoneInfo class that reads TZif data and creates objects that represent tzdb timezones. Python is freely available under the -Python Software Foundation +Python Software Foundation License. A companion PyPI module tzdata @@ -641,7 +635,7 @@

    Other tz-based time zone softwareFoxClocks is an extension for Google Chrome and for Mozilla +href="https://wiki.mozilla.org/Modules/Toolkit">Mozilla Toolkit applications like Firefox and Thunderbird. @@ -873,7 +867,7 @@

    National histories of legal time

    zones and daylight saving time.
    Chile
    The Hydrographic and Oceanographic Service of the Chilean Navy publishes a -history of +history of Chile's official time (in Spanish).
    China
    The Hong Kong Observatory maintains a @@ -1010,14 +1004,11 @@

    Precision timekeeping

    href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol">DHCP option for a server to configure a client's time zone and daylight saving settings automatically.
  • -
  • Astronomical -Times explains more abstruse astronomical time scales like +
  • Time +Scales describes astronomical time scales like TDT, TCG, and TDB. -Time -Scales goes into more detail, particularly for historical variants.
  • The IAU's # Korn Shell -# MirBSD Korn Shell +# MirBSD Korn Shell # -# For portability to Solaris 9 /bin/sh this script avoids some POSIX -# features and common extensions, such as $(...) (which works sometimes -# but not others), $((...)), and $10. +# For portability to Solaris 10 /bin/sh (supported by Oracle through +# January 2024) this script avoids some POSIX features and common +# extensions, such as $(...) (which works sometimes but not others), +# $((...)), ! CMD, ${#ID}, ${ID##PAT}, ${ID%%PAT}, and $10. + # # This script also uses several features of modern awk programs. # If your host lacks awk, or has an old awk that does not conform to Posix, @@ -101,14 +103,6 @@ then esac done || exit } - - # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout. - case $BASH_VERSION in - [01].*) - case `echo 1 | (select x in x; do break; done) 2>/dev/null` in - ?*) PS3= - esac - esac ' else doselect() { @@ -185,7 +179,7 @@ done # If the current locale does not support UTF-8, convert data to current # locale's format if possible, as the shell aligns columns better that way. # Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI. -! $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' && +$AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' || { { tmp=`(mktemp -d) 2>/dev/null` || { tmp=${TMPDIR-/tmp}/tzselect.$$ && (umask 77 && mkdir -- "$tmp") @@ -196,6 +190,7 @@ done TZ_COUNTRY_TABLE=$tmp/iso3166.tab && iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab && TZ_ZONE_TABLE=$tmp/$zonetabtype.tab +} newline=' ' diff --git a/zdump.8 b/zdump.8 index a5e2042..131a6cb 100644 --- a/zdump.8 +++ b/zdump.8 @@ -17,7 +17,7 @@ zdump \- timezone dumper \\$3\*(lq\\$1\*(rq\\$2 .. .ie \n(.g .ds - \f(CW-\fP -.el ds - \- +.el .ds - \- The .B zdump program prints the current time in each diff --git a/zdump.c b/zdump.c index e198b04..8b6788a 100644 --- a/zdump.c +++ b/zdump.c @@ -56,6 +56,21 @@ */ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 }; +#if !defined HAVE_GENERIC && defined __has_extension +# if __has_extension(c_generic_selections) +# define HAVE_GENERIC 1 +# else +# define HAVE_GENERIC 0 +# endif +#endif +/* _Generic is buggy in pre-4.9 GCC. */ +#if !defined HAVE_GENERIC && defined __GNUC__ +# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__)) +#endif +#ifndef HAVE_GENERIC +# define HAVE_GENERIC (201112 <= __STDC_VERSION__) +#endif + #if HAVE_GETTEXT #include /* for setlocale */ #endif /* HAVE_GETTEXT */ @@ -131,7 +146,7 @@ sumsize(size_t a, size_t b) { size_t sum = a + b; if (sum < a) { - fprintf(stderr, "%s: size overflow\n", progname); + fprintf(stderr, _("%s: size overflow\n"), progname); exit(EXIT_FAILURE); } return sum; @@ -798,6 +813,7 @@ show(timezone_t tz, char *zone, time_t t, bool v) gmtmp = my_gmtime_r(&t, &gmtm); if (gmtmp == NULL) { printf(tformat(), t); + printf(_(" (gmtime failed)")); } else { dumptime(gmtmp); printf(" UT"); @@ -805,8 +821,11 @@ show(timezone_t tz, char *zone, time_t t, bool v) printf(" = "); } tmp = my_localtime_rz(tz, &t, &tm); - dumptime(tmp); - if (tmp != NULL) { + if (tmp == NULL) { + printf(tformat(), t); + printf(_(" (localtime failed)")); + } else { + dumptime(tmp); if (*abbr(tmp) != '\0') printf(" %s", abbr(tmp)); if (v) { @@ -1119,12 +1138,29 @@ abbr(struct tm const *tmp) /* ** The code below can fail on certain theoretical systems; -** it works on all known real-world systems as of 2004-12-30. +** it works on all known real-world systems as of 2022-01-25. */ static const char * tformat(void) { +#if HAVE_GENERIC + /* C11-style _Generic is more likely to return the correct + format when distinct types have the same size. */ + char const *fmt = + _Generic(+ (time_t) 0, + int: "%d", long: "%ld", long long: "%lld", + unsigned: "%u", unsigned long: "%lu", + unsigned long long: "%llu", + default: NULL); + if (fmt) + return fmt; + fmt = _Generic((time_t) 0, + intmax_t: "%"PRIdMAX, uintmax_t: "%"PRIuMAX, + default: NULL); + if (fmt) + return fmt; +#endif if (0 > (time_t) -1) { /* signed */ if (sizeof(time_t) == sizeof(intmax_t)) return "%"PRIdMAX; @@ -1158,10 +1194,6 @@ dumptime(register const struct tm *timeptr) register int lead; register int trail; - if (timeptr == NULL) { - printf("NULL"); - return; - } /* ** The packaged localtime_rz and gmtime_r never put out-of-range ** values in tm_wday or tm_mon, but since this code might be compiled diff --git a/zic.8 b/zic.8 index ea7bab9..a0a9743 100644 --- a/zic.8 +++ b/zic.8 @@ -122,7 +122,7 @@ is any already-existing link is removed. .TP .BR "\*-r " "[\fB@\fP\fIlo\fP][\fB/@\fP\fIhi\fP]" -Reduce the size of output files by limiting their applicability +Limit the applicability of output files to timestamps in the range from .I lo (inclusive) to @@ -134,6 +134,10 @@ and are possibly-signed decimal counts of seconds since the Epoch (1970-01-01 00:00:00 UTC). Omitted counts default to extreme values. +The output files use UT offset 0 and abbreviation +.q "\*-00" +in place of the omitted timestamp data; +this typically reduces the files' sizes. For example, .q "zic \*-r @0" omits data intended for negative timestamps (i.e., before the Epoch), and @@ -523,8 +527,8 @@ begin the field with a minus sign if time must be subtracted from UT. .B RULES The name of the rules that apply in the timezone or, alternatively, a field in the same format as a rule-line SAVE column, -giving of the amount of time to be added to local standard time -effect, and whether the resulting time is standard or daylight saving. +giving the amount of time to be added to local standard time +and whether the resulting time is standard or daylight saving. If this field is .B \*- then standard time always applies. @@ -559,6 +563,9 @@ alphanumeric ASCII characters, .q "+" and .q "\*-". +By convention, the time zone abbreviation +.q "\*-00" +is a placeholder that means local time is unspecified. .TP .B UNTIL The time at which the UT offset or the rule(s) change for a location. diff --git a/zic.c b/zic.c index 0101351..2d1a187 100644 --- a/zic.c +++ b/zic.c @@ -202,6 +202,7 @@ static const char * progname; static ptrdiff_t timecnt; static ptrdiff_t timecnt_alloc; static int typecnt; +static int unspecifiedtype; /* ** Line codes. @@ -989,9 +990,10 @@ random_dirent(char const **name, char **namealloc) char const *src = *name; char *dst = *namealloc; static char const prefix[] = ".zic"; - static char const alphabet[] = ("abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789"); + static char const alphabet[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; enum { prefixlen = sizeof prefix - 1, alphabetlen = sizeof alphabet - 1 }; int suffixlen = 6; char const *lastslash = strrchr(src, '/'); @@ -1972,6 +1974,10 @@ limitrange(struct timerange r, bool locut, zic_t lo, zic_t hi, r.base++; } + /* "-00" before any -r low cutoff. */ + if (min_time < lo_time) + r.defaulttype = unspecifiedtype; + /* Omit as many initial leap seconds as possible, such that the first leap second in the truncated list is <= LO, and is a positive leap second if and only if it has a positive correction. @@ -2120,7 +2126,7 @@ writezone(const char *const name, const char *const string, char version, rangeall.pretrans = rangeall.leapexpiry = false; range64 = limitrange(rangeall, min_time < lo_time, lo_time, hi_time, ats, types); - range32 = limitrange(range64, INT32_MIN < lo_time || want_bloat(), + range32 = limitrange(range64, true, INT32_MIN, INT32_MAX, ats, types); /* TZif version 4 is needed if a no-op transition is appended to @@ -2155,7 +2161,7 @@ writezone(const char *const name, const char *const string, char version, register ptrdiff_t thistimei, thistimecnt, thistimelim; register int thisleapi, thisleapcnt, thisleaplim; struct tzhead tzh; - int currenttype, thisdefaulttype; + int thisdefaulttype; bool hicut, pretrans, thisleapexpiry; zic_t lo; int old0; @@ -2205,13 +2211,12 @@ writezone(const char *const name, const char *const string, char version, error(_("too many transition times")); thistimelim = thistimei + thistimecnt; - if (thistimecnt && hi_time < max_time - && ats[thistimelim - 1] == hi_time + 1) - hicut = false; memset(omittype, true, typecnt); omittype[thisdefaulttype] = false; for (i = thistimei - pretrans; i < thistimelim; i++) omittype[types[i]] = false; + if (hicut) + omittype[unspecifiedtype] = false; /* Reorder types to make THISDEFAULTTYPE type 0. Use TYPEMAP to swap OLD0 and THISDEFAULTTYPE so that @@ -2347,13 +2352,10 @@ writezone(const char *const name, const char *const string, char version, } if (hicut) puttzcodepass(hi_time + 1, fp, pass); - currenttype = 0; - for (i = thistimei - pretrans; i < thistimelim; ++i) { - currenttype = typemap[types[i]]; - putc(currenttype, fp); - } + for (i = thistimei - pretrans; i < thistimelim; ++i) + putc(typemap[types[i]], fp); if (hicut) - putc(currenttype, fp); + putc(typemap[unspecifiedtype], fp); for (i = old0; i < typecnt; i++) { int h = (i == old0 ? thisdefaulttype @@ -2868,6 +2870,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) max_year = 2038; } + if (min_time < lo_time || hi_time < max_time) + unspecifiedtype = addtype(0, "-00", false, false, false); + for (i = 0; i < zonecount; ++i) { struct rule *prevrp = NULL; zic_t prevktime; @@ -3559,9 +3564,11 @@ mkdirs(char const *argname, bool ancestors) if (mkdir(name, MKDIR_UMASK) != 0) { /* Do not report an error if err == EEXIST, because some other process might have made the directory - in the meantime. */ + in the meantime. Likewise for ENOSYS, because + Solaris 10 mkdir fails with ENOSYS if the + directory is an automounted mount point. */ int err = errno; - if (err != EEXIST) { + if (err != EEXIST && err != ENOSYS) { error(_("%s: Can't create directory %s: %s"), progname, name, strerror(err)); exit(EXIT_FAILURE); diff --git a/ziguard.awk b/ziguard.awk index 6888c27..2be6d52 100644 --- a/ziguard.awk +++ b/ziguard.awk @@ -104,13 +104,19 @@ DATAFORM != "main" { } if (!vanguard && $1 == "Rule" && $2 == "Morocco" && 2019 <= $3) { if ($9 == "0") { + last_std_date = $3 " " $6 " " $7 " " $8 sub(/\t0\t/, "\t1:00\t") } else { sub(/\t-1:00\t/, "\t0\t") } } if (!vanguard && $1 == "1:00" && $2 == "Morocco" && $3 == "+01/+00") { - sub(/1:00\tMorocco\t\+01\/\+00$/, "0:00\tMorocco\t+00/+01") + # This introduces a transition from 01:59:59 +00 to 03:00:00 +01 + # with both times being standard (i.e., a change to standard UT offset). + # This is rearguard's way to approximate the actual prediction, + # which is that of an ordinary transition from DST to standard time. + sub(/1:00\tMorocco\t\+01\/\+00$/, + "0:00\tMorocco\t+00/+01\t" last_std_date "\n\t\t\t 1:00\t-\t+01") } }