Skip to content

Commit

Permalink
New tzselect menu option ‘now’
Browse files Browse the repository at this point in the history
* Makefile (ZONETABLES, VERSION_DEPS): Add zonenow.tab.
(CHECK_NOW_TIMESTAMP, CHECK_NOW_FUTURE_YEARS, CHECK_NOW_FUTURE_SECS):
New macros.
(check_now): New target rule.
(check_mild): Depend on it.
* NEWS: Mention this new feature.
* checknow.awk, zonenow.tab: New files.
* checktab.awk: Adjust (i.e., loosen) checks for zonenow.tab.
* tzselect.ksh (TZ_ZONETABTYPE_TABLE, TZ_ZONENOW_TABLE):
New vars, so that the code can switch back and for easily between
zone1970.tab and zonenow.tab.
(TZ_ZONE_TABLE): Set to one of those two vars, depending on user.
Let users choose ‘now’ if they care only about timestamps from now on.
Narrow ‘regions’ based on ‘now’ selection, if possible (which it
always is, with the current data).
  • Loading branch information
eggert committed Dec 19, 2023
1 parent d001fb9 commit c333318
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 14 deletions.
31 changes: 27 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 \
Expand Down
11 changes: 11 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -25,13 +26,23 @@ 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
transition into a DST regime. Previously, it incorrectly assumed
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:
Expand Down
53 changes: 53 additions & 0 deletions checknow.awk
Original file line number Diff line number Diff line change
@@ -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 <zdump_table) {
if ($0 ~ /^TZ/) {
record_zone(zone, data)
zone = $0
sub(/.*\.dir\//, "", zone)
sub(/"/, "", zone)
data = ""
} else if ($0 ~ /./)
data = data $0 "\n"
}
record_zone(zone, data)
FS = "\t"
}

/^[^#]/ {
zone = $3
data = zone_data[zone]
if (!data) {
printf "%s: no data\n"
status = 1
} else {
zone2 = zonenow[data]
if (zone2) {
printf "zones %s and %s identical from now on\n", zone, zone2
status = 1
} else
zonenow[data] = zone
}
}

END {
for (zone in zone_data) {
data = zone_data[zone]
if (!zonenow[data]) {
printf "checknow.tab should have one of:%s\n", zones[data]
zonenow[data] = zone # This suppresses duplicate diagnostics.
status = 1
}
}
exit status
}
7 changes: 4 additions & 3 deletions checktab.awk
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ BEGIN {
cc = cca[i]
if (cc2name[cc]) {
cc_used[cc]++
} else {
} else if (! (cc == "XX" && zone_table == "zonenow.tab")) {
printf "%s:%d: %s: unknown country code\n", \
zone_table, zone_NR, cc >>"/dev/stderr"
status = 1
Expand All @@ -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"
Expand Down Expand Up @@ -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
Expand Down
49 changes: 42 additions & 7 deletions tzselect.ksh
Original file line number Diff line number Diff line change
Expand Up @@ -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='
'
Expand Down Expand Up @@ -385,6 +386,7 @@ while
country_result=
region=
time=
TZ_ZONE_TABLE=$TZ_ZONETABTYPE_TABLE

case $coord in
?*)
Expand All @@ -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 '
Expand All @@ -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 ~ /^[^#]/)
Expand All @@ -421,7 +424,7 @@ while
}
}
}
' ="$TZ_ZONE_TABLE" |
' ="$TZ_ZONETABTYPE_TABLE" |
sort -u |
tr '\n' ' '
echo ''
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit c333318

Please sign in to comment.