diff --git a/Makefile b/Makefile index a6051531..f473af67 100644 --- a/Makefile +++ b/Makefile @@ -580,7 +580,7 @@ YDATA= $(PRIMARY_YDATA) etcetera NDATA= factory TDATA_TO_CHECK= $(YDATA) $(NDATA) backward TDATA= $(YDATA) $(NDATA) $(BACKWARD) -ZONETABLES= zone1970.tab zone.tab +ZONETABLES= zone.tab zone1970.tab zonenow.tab TABDATA= iso3166.tab $(TZDATA_TEXT) $(ZONETABLES) LEAP_DEPS= leapseconds.awk leap-seconds.list TZDATA_ZI_DEPS= ziguard.awk zishrink.awk version $(TDATA) \ @@ -619,7 +619,7 @@ VERSION_DEPS= \ tzfile.5 tzfile.h tzselect.8 tzselect.ksh \ workman.sh zdump.8 zdump.c zic.8 zic.c \ ziguard.awk zishrink.awk \ - zone.tab zone1970.tab + zone.tab zone1970.tab zonenow.tab all: tzselect zic zdump libtz.a $(TABDATA) \ vanguard.zi main.zi rearguard.zi @@ -825,7 +825,8 @@ tzselect: tzselect.ksh version check: check_back check_mild check_mild: check_character_set check_white_space check_links \ - check_name_lengths check_slashed_abbrs check_sorted \ + check_name_lengths check_now \ + check_slashed_abbrs check_sorted \ check_tables check_web check_ziguard check_zishrink check_tzs check_character_set: $(ENCHILADA) @@ -893,7 +894,29 @@ check_links: checklinks.awk tzdata.zi -f checklinks.awk tzdata.zi touch $@ -check_tables: checktab.awk $(YDATA) backward $(ZONETABLES) +# Check timestamps from now through 28 years from now, to make sure +# that zonenow.tab contains all sequences of planned timestamps, +# without any duplicate sequences. In theory this might require +# 2800 years but that would take a long time to check. +CHECK_NOW_TIMESTAMP = `./date +%s` +CHECK_NOW_FUTURE_YEARS = 28 +CHECK_NOW_FUTURE_SECS = $(CHECK_NOW_FUTURE_YEARS) '*' 366 '*' 24 '*' 60 '*' 60 +check_now: checknow.awk date tzdata.zi zdump zic zone1970.tab zonenow.tab + rm -fr $@.dir + mkdir $@.dir + ./zic -d $@.dir tzdata.zi + now=$(CHECK_NOW_TIMESTAMP) && \ + future=`expr $(CHECK_NOW_FUTURE_SECS) + $$now` && \ + ./zdump -i -t $$now,$$future \ + $$(find $$PWD/$@.dir/????*/ -type f) \ + >$@.dir/zdump.tab + $(AWK) \ + -v zdump_table=$@.dir/zdump.tab \ + -f checknow.awk zonenow.tab + rm -fr $@.dir + touch $@ + +check_tables: checktab.awk $(YDATA) backward zone.tab zone1970.tab for tab in $(ZONETABLES); do \ test "$$tab" = zone.tab && links='$(BACKWARD)' || links=''; \ $(AWK) -f checktab.awk -v zone_table=$$tab $(YDATA) $$links \ diff --git a/NEWS b/NEWS index f2d0bc3c..43070aae 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ Unreleased, experimental changes Briefly: Ittoqqortoormiit, Greenland changes time zones on 2024-03-31. Code and data fixes for Palestine timestamps starting in 2072. + A new data file zonenow.tab for timestamps starting now. Changes to future timestamps @@ -25,6 +26,13 @@ Unreleased, experimental changes This does not affect UTC offsets, only the tm_isdst flag. (Thanks to Thomas M. Steenholdt.) + New data file + + A new data file zonenow.tab helps configure applications that use + timestamps dated from now on. This simplifies configuration, + since users choose from a smaller Zone set. The file's format is + experimental and subject to change. + Changes to code localtime.c no longer mishandles TZif files that contain a single @@ -32,6 +40,9 @@ Unreleased, experimental changes DST was in effect before the transition too. (Thanks to Alois Treindl for debugging help.) + tzselect now optionally reads zonenow.tab, to simplify when + configuring only for timestamps dated from now on. + tzselect no longer creates temporary files. tzselect no longer mishandles the following: diff --git a/checknow.awk b/checknow.awk new file mode 100644 index 00000000..51ee998f --- /dev/null +++ b/checknow.awk @@ -0,0 +1,53 @@ +# Check zonenow.tab for consistency with primary data. + +# Contributed by Paul Eggert. This file is in the public domain. + +function record_zone(zone, data) { + if (zone) { + zone_data[zone] = data + zones[data] = zones[data] " " zone + } +} + +BEGIN { + while (getline >"/dev/stderr" status = 1 @@ -110,7 +110,7 @@ BEGIN { used_max_cc = cc } } - if (used_max <= 1 && comments) { + if (used_max <= 1 && comments && zone_table != "zonenow.tab") { printf "%s:%d: unnecessary comment '%s'\n", \ zone_table, i, comments \ >>"/dev/stderr" @@ -149,7 +149,8 @@ $1 ~ /^#/ { next } if ($3 ~ /%/) rulePercentUsed[$2] = 1 } if (tz && tz ~ /\// && tz !~ /^Etc\//) { - if (!tztab[tz] && FILENAME != "backward") { + if (!tztab[tz] && FILENAME != "backward" \ + && zone_table != "zonenow.tab") { printf "%s: no data for '%s'\n", zone_table, tz \ >>"/dev/stderr" status = 1 diff --git a/tzselect.ksh b/tzselect.ksh index f894bb56..70bda9c0 100644 --- a/tzselect.ksh +++ b/tzselect.ksh @@ -196,7 +196,8 @@ read_file() { } } read_file TZ_COUNTRY_TABLE "$TZDIR/iso3166.tab" -read_file TZ_ZONE_TABLE "$TZDIR/$zonetabtype.tab" +read_file TZ_ZONETABTYPE_TABLE "$TZDIR/$zonetabtype.tab" +TZ_ZONENOW_TABLE= newline=' ' @@ -385,6 +386,7 @@ while country_result= region= time= + TZ_ZONE_TABLE=$TZ_ZONETABTYPE_TABLE case $coord in ?*) @@ -393,7 +395,8 @@ while # Ask the user for continent or ocean. - echo >&2 'Please select a continent, ocean, "coord", "TZ", or "time".' + echo >&2 \ + 'Please select a continent, ocean, "coord", "TZ", "time", or "now".' quoted_continents=` $AWK ' @@ -406,10 +409,10 @@ while printf "'\''%s'\''\n", entry } BEGIN { - TZ_ZONE_TABLE = substr(ARGV[1], 2) + TZ_ZONETABTYPE_TABLE = substr(ARGV[1], 2) ARGV[1] = "" FS = "\t" - nlines = split(TZ_ZONE_TABLE, line, /\n/) + nlines = split(TZ_ZONETABTYPE_TABLE, line, /\n/) for (i = 1; i <= nlines; i++) { $0 = line[i] if ($0 ~ /^[^#]/) @@ -421,7 +424,7 @@ while } } } - ' ="$TZ_ZONE_TABLE" | + ' ="$TZ_ZONETABTYPE_TABLE" | sort -u | tr '\n' ' ' echo '' @@ -431,12 +434,19 @@ while doselect '"$quoted_continents"' \ "coord - I want to use geographical coordinates." \ "TZ - I want to specify the timezone using the POSIX TZ format." \ - "time - I know local time already." + "time - I know local time already." \ + "now - Like \"time\", but configure only for timestamps from now on." continent=$select_result case $continent in Americas) continent=America;; *" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''` esac + case $zonetabtype,$continent in + zonenow,*) ;; + *,now) + ${TZ_ZONENOW_TABLE:+:} read_file TZ_ZONENOW_TABLE "$TZDIR/zonenow.tab" + TZ_ZONE_TABLE=$TZ_ZONENOW_TABLE + esac ' esac @@ -529,7 +539,7 @@ while `;; *) case $continent in - time) + now|time) minute_format='%a %b %d %H:%M' old_minute=`TZ=UTC0 date +"$minute_format"` for i in 1 2 3 @@ -609,6 +619,31 @@ while ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | sort -f ` + # If all zone table entries have comments, and there are + # at most 22 entries, asked based on those comments. + # This fits the prompt onto old-fashioned 24-line screens. + regions=` + $AWK ' + BEGIN { + TZ_ZONE_TABLE = substr(ARGV[1], 2) + ARGV[1] = "" + FS = "\t" + nlines = split(TZ_ZONE_TABLE, line, /\n/) + for (i = 1; i <= nlines; i++) { + $0 = line[i] + if ($0 ~ /^[^#]/ && !missing_comment) { + if ($4) + comment[++inlines] = $4 + else + missing_comment = 1 + } + } + if (!missing_comment && inlines <= 22) + for (i = 1; i <= inlines; i++) + print comment[i] + } + ' ="$zone_table" + ` # If there's more than one country, ask the user which one. case $countries in diff --git a/zonenow.tab b/zonenow.tab new file mode 100644 index 00000000..b1c1f332 --- /dev/null +++ b/zonenow.tab @@ -0,0 +1,298 @@ +# tzdb timezone descriptions, for users who do not care about old timestamps +# +# This file is in the public domain. +# +# From Paul Eggert (2023-12-18): +# This file contains a table where each row stands for a timezone +# where civil timestamps are predicted to agree from now on. +# This file is like zone1970.tab (see zone1970.tab's coments), +# but with the following changes: +# +# 1. Each timezone corresponds to a set of clocks that are planned +# to agree from now on. This is a larger set of clocks than in +# zone1970.tab, where each timezone's clocks must agree from 1970 on. +# 2. The first column is irrelevant and ignored. +# 3. The table is sorted in a different way: +# first by standard time UTC offset; +# then, if DST is used, by daylight saving UTC offset; +# then by time zone abbreviation. +# +# The format of this table is experimental, and may change in future versions. +# +# This table is intended as an aid for users, to help them select timezones +# appropriate for their practical needs. It is not intended to take or +# endorse any position on legal or territorial claims. +# +#XX coordinates TZ comments +# +# -11 - SST +XX -1416-17042 Pacific/Pago_Pago Midway; Samoa ("SST") +# +# -11 +XX -1901-16955 Pacific/Niue Niue +# +# -10 - HST +XX +211825-1575130 Pacific/Honolulu Hawaii ("HST") +# +# -10 +XX -1732-14934 Pacific/Tahiti Tahiti; Cook Islands +# +# -10/-09 - HST / HDT (North America DST) +XX +515248-1763929 America/Adak western Aleutians in Alaska ("HST/HDT") +# +# -09:30 +XX -0900-13930 Pacific/Marquesas Marquesas +# +# -09 +XX -2308-13457 Pacific/Gambier Gambier +# +# -09/-08 - AKST/AKDT (North America DST) +XX +611305-1495401 America/Anchorage most of Alaska ("AKST/AKDT") +# +# -08 +XX -2504-13005 Pacific/Pitcairn Pitcairn +# +# -08/-07 - PST/PDT (North America DST) +XX +340308-1181434 America/Los_Angeles Pacific ("PST/PDT") - US & Canada; Mexico near US border +# +# -07 - MST +XX +332654-1120424 America/Phoenix Mountain Standard ("MST") - Arizona; western Mexico; Yukon +# +# -07/-06 - MST/MDT (North America DST) +XX +394421-1045903 America/Denver Mountain ("MST/MDT") - US & Canada; Mexico near US border +# +# -06 +XX -0054-08936 Pacific/Galapagos Galápagos +# +# -06 - CST +XX +1924-09909 America/Mexico_City Central Standard ("CST") - Saskatchewan; central Mexico; Central America +# +# -06/-05 (Chile DST) +XX -2709-10926 Pacific/Easter Easter Island +# +# -06/-05 - CST/CDT (North America DST) +XX +415100-0873900 America/Chicago Central ("CST/CDT") - US & Canada; Mexico near US border +# +# -05 +XX -1203-07703 America/Lima eastern South America +# +# -05 - EST +XX +175805-0764736 America/Jamaica Eastern Standard ("EST") - Caymans; Jamaica; eastern Mexico; Panama +# +# -05/-04 - CST/CDT (Cuba DST) +XX +2308-08222 America/Havana Cuba +# +# -05/-04 - EST/EDT (North America DST) +XX +404251-0740023 America/New_York Eastern ("EST/EDT") - US & Canada +# +# -04 +XX +1030-06656 America/Caracas western South America +# +# -04 - AST +XX +1828-06954 America/Santo_Domingo Atlantic Standard ("AST") - eastern Caribbean +# +# -04/-03 (Chile DST) +XX -3327-07040 America/Santiago most of Chile +# +# -04/-03 (Paraguay DST) +XX -2516-05740 America/Asuncion Paraguay +# +# -04/-03 - AST/ADT (North America DST) +XX +4439-06336 America/Halifax Atlantic ("AST/ADT") - Canada; Bermuda +# +# -03:30/-02:30 - NST/NDT (North America DST) +XX +4734-05243 America/St_Johns Newfoundland ("NST/NDT") +# +# -03 +XX -2332-04637 America/Sao_Paulo eastern South America +# +# -03/-02 (North America DST) +XX +4703-05620 America/Miquelon St Pierre & Miquelon +# +# -02 +XX -0351-03225 America/Noronha Fernando de Noronha; South Georgia +# +# -02/-01 (EU DST) +XX +6411-05144 America/Nuuk most of Greenland +# +# -01 +XX +1455-02331 Atlantic/Cape_Verde Cape Verde +# +# -01/+00 (EU DST) +XX +3744-02540 Atlantic/Azores Azores +# -01/+00 (EU DST) until 2024-03-01; then -02/-01 (EU DST) +XX +7029-02158 America/Scoresbysund Ittoqqortoormiit +# +# +00 - GMT +XX +0519-00402 Africa/Abidjan far western Africa; Iceland ("GMT") +# +# +00/+01 - GMT/BST (EU DST) +XX +513030-0000731 Europe/London United Kingdom ("GMT/BST") +# +# +00/+01 - WET/WEST (EU DST) +XX +3843-00908 Europe/Lisbon western Europe ("WET/WEST") +# +# +00/+01 - Troll DST +XX -720041+0023206 Antarctica/Troll Troll Station in Antarctica +# +# +01 - CET +XX +3647+00303 Africa/Algiers Algeria, Tunisia ("CET") +# +# +01 - WAT +XX +0627+00324 Africa/Lagos western Africa ("WAT") +# +# +01/+00 - IST/GMT (EU DST in reverse) +XX +5320-00615 Europe/Dublin Ireland ("IST/GMT") +# +# +01/+00 - (Morocco DST) +XX +3339-00735 Africa/Casablanca Morocco +# +# +01/+02 - CET/CEST (EU DST) +XX +4852+00220 Europe/Paris central Europe ("CET/CEST") +# +# +02 - CAT +XX -2558+03235 Africa/Maputo central Africa ("CAT") +# +# +02 - EET +XX +3254+01311 Africa/Tripoli Libya; Kaliningrad ("EET") +# +# +02 - SAST +XX -2615+02800 Africa/Johannesburg southern Africa ("SAST") +# +# +02/+03 - EET/EEST (EU DST) +XX +3758+02343 Europe/Athens eastern Europe ("EET/EEST") +# +# +02/+03 - EET/EEST (Egypt DST) +XX +3003+03115 Africa/Cairo Egypt +# +# +02/+03 - EET/EEST (Lebanon DST) +XX +3353+03530 Asia/Beirut Lebanon +# +# +02/+03 - EET/EEST (Moldova DST) +XX +4700+02850 Europe/Chisinau Moldova +# +# +02/+03 - EET/EEST (Palestine DST) +XX +3130+03428 Asia/Gaza Palestine +# +# +02/+03 - IST/IDT (Israel DST) +XX +314650+0351326 Asia/Jerusalem Israel +# +# +03 +XX +4101+02858 Europe/Istanbul Near East; Belarus +# +# +03 - EAT +XX -0117+03649 Africa/Nairobi eastern Africa ("EAT") +# +# +03 - MSK +XX +554521+0373704 Europe/Moscow Moscow ("MSK") +# +# +03:30 +XX +3540+05126 Asia/Tehran Iran +# +# +04 +XX +2518+05518 Asia/Dubai Russia; Caucasus; Persian Gulf; Seychelles; Réunion +# +# +04:30 +XX +3431+06912 Asia/Kabul Afghanistan +# +# +05 +XX +4120+06918 Asia/Tashkent Russia; Tajikistan; Turkmenistan; Uzbekistan; Maldives +# +# +05 - PKT +XX +2452+06703 Asia/Karachi Pakistan ("PKT") +# +# +05:30 +XX +0656+07951 Asia/Colombo Sri Lanka +# +# +05:30 - IST +XX +2232+08822 Asia/Kolkata India ("IST") +# +# +05:45 +XX +2743+08519 Asia/Kathmandu Nepal +# +# +06 +XX +2343+09025 Asia/Dhaka Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos +# +# +06:30 +XX +1647+09610 Asia/Yangon Myanmar; Cocos +# +# +07 +XX +1345+10031 Asia/Bangkok Russia; Indochina; Christmas Island +# +# +07 - WIB +XX -0610+10648 Asia/Jakarta Indonesia ("WIB") +# +# +08 +XX +0117+10351 Asia/Singapore Russia; Brunei; Malaysia; Singapore +# +# +08 - AWST +XX -3157+11551 Australia/Perth Western Australia ("AWST") +# +# +08 - CST +XX +3114+12128 Asia/Shanghai China ("CST") +# +# +08 - HKT +XX +2217+11409 Asia/Hong_Kong Hong Kong ("HKT") +# +# +08 - PHT +XX +1435+12100 Asia/Manila Philippines ("PHT") +# +# +08 - WITA +XX -0507+11924 Asia/Makassar Indonesia ("WITA") +# +# +08:45 +XX -3143+12852 Australia/Eucla Eucla +# +# +09 +XX +5203+11328 Asia/Chita Russia; Palau; East Timor +# +# +09 - JST +XX +353916+1394441 Asia/Tokyo Japan ("JST") +# +# +09 - KST +XX +3733+12658 Asia/Seoul Korea ("KST") +# +# +09 - WIT +XX -0232+14042 Asia/Jayapura Indonesia ("WIT") +# +# +09:30 - ACST +XX -1228+13050 Australia/Darwin Northern Territory ("ACST") +# +# +09:30/+10:30 - ACST/ACDT (Australia DST) +XX -3455+13835 Australia/Adelaide South Australia ("ACST/ACDT") +# +# +10 +XX +4310+13156 Asia/Vladivostok Russia; Yap; Chuuk; Papua New Guinea; Dumont d'Urville +# +# +10 - AEST +XX -2728+15302 Australia/Brisbane Queensland ("AEST") +# +# +10 - ChST +XX +1328+14445 Pacific/Guam Mariana Islands ("ChST") +# +# +10/+11 - AEST/AEDT (Australia DST) +XX -3352+15113 Australia/Sydney southeast Australia ("AEST/AEDT") +# +# +10:30/+11 +XX -3133+15905 Australia/Lord_Howe Lord Howe Island +# +# +11 +XX -0613+15534 Pacific/Bougainville Russia; Kosrae; Bougainville; Solomons +# +# +11/+12 (Australia DST) +XX -2903+16758 Pacific/Norfolk Norfolk Island +# +# +12 +XX +5301+15839 Asia/Kamchatka Russia; Tuvalu; Fiji; etc. +# +# +12/+13 (New Zealand DST) +XX -3652+17446 Pacific/Auckland New Zealand ("NZST/NZDT") +# +# +12:45/+13:45 (Chatham DST) +XX -4357-17633 Pacific/Chatham Chatham Islands +# +# +13 +XX -210800-1751200 Pacific/Tongatapu Kanton; Tokelau; Samoa (western); Tonga +# +# +14 +XX +0152-15720 Pacific/Kiritimati Kiritimati