git: e257a38de4d5 - stable/14 - Update tzcode to 2024a.

From: Dag-Erling Smørgrav <des_at_FreeBSD.org>
Date: Wed, 21 Feb 2024 20:59:18 UTC
The branch stable/14 has been updated by des:

URL: https://cgit.FreeBSD.org/src/commit/?id=e257a38de4d57bb1884d5c7196131a81192d5252

commit e257a38de4d57bb1884d5c7196131a81192d5252
Author:     Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2024-02-13 20:20:44 +0000
Commit:     Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2024-02-21 20:33:23 +0000

    Update tzcode to 2024a.
    
    MFC after:      3 weeks
    Sponsored by:   Klara, Inc.
    
    (cherry picked from commit 46c599340f187db577b9212ab18022f3c7380c68)
---
 contrib/tzcode/Makefile      |  261 +++++++----
 contrib/tzcode/NEWS          |  193 +++++++-
 contrib/tzcode/README        |   19 +-
 contrib/tzcode/date.1        |   14 +-
 contrib/tzcode/localtime.c   |  128 +++---
 contrib/tzcode/newctime.3    |   16 +-
 contrib/tzcode/newstrftime.3 |  152 ++++++-
 contrib/tzcode/newtzset.3    |  206 +++++----
 contrib/tzcode/private.h     |   44 +-
 contrib/tzcode/strftime.c    |    7 +-
 contrib/tzcode/theory.html   |   37 +-
 contrib/tzcode/tz-art.html   |  419 ++++++++----------
 contrib/tzcode/tz-link.html  |  118 +++--
 contrib/tzcode/tzdir.h       |    6 +
 contrib/tzcode/tzfile.5      |   32 +-
 contrib/tzcode/tzfile.h      |   14 +-
 contrib/tzcode/tzselect.8    |    2 +-
 contrib/tzcode/tzselect.ksh  | 1006 +++++++++++++++++++++++-------------------
 contrib/tzcode/version       |    2 +-
 contrib/tzcode/zdump.c       |    2 +-
 contrib/tzcode/zic.8         |   35 +-
 contrib/tzcode/zic.c         |  239 +++++-----
 lib/libc/gen/sysconf.c       |    2 +-
 lib/libc/stdtime/strftime.c  |    2 +-
 24 files changed, 1767 insertions(+), 1189 deletions(-)

diff --git a/contrib/tzcode/Makefile b/contrib/tzcode/Makefile
index 0e56af89e2a4..d48354c72df4 100644
--- a/contrib/tzcode/Makefile
+++ b/contrib/tzcode/Makefile
@@ -1,7 +1,25 @@
 # Make and install tzdb code and data.
-
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
+# Request POSIX conformance; this must be the first non-comment line.
+.POSIX:
+# On older platforms you may need to scrounge for a POSIX-conforming 'make'.
+# For example, on Solaris 10 (2005), use /usr/sfw/bin/gmake or
+# /usr/xpg4/bin/make, not /usr/ccs/bin/make.
+
+# To affect how this Makefile works, you can run a shell script like this:
+#
+#	#!/bin/sh
+#	make CC='gcc -std=gnu11' "$@"
+#
+# This example script is appropriate for a pre-2017 GNU/Linux system
+# where a non-default setting is needed to support this package's use of C99.
+#
+# Alternatively, you can simply edit this Makefile to tailor the following
+# macro definitions.
+
+###############################################################################
+# Start of macros that one plausibly might want to tailor.
 
 # Package name for the code distribution.
 PACKAGE=	tzcode
@@ -35,7 +53,7 @@ DATAFORM=		main
 
 LOCALTIME=	Factory
 
-# The POSIXRULES macro controls interpretation of POSIX-like TZ
+# The POSIXRULES macro controls interpretation of POSIX-2017.1-like TZ
 # settings like TZ='EET-2EEST' that lack DST transition rules.
 # If POSIXRULES is '-', no template is installed; this is the default.
 # Any other value for POSIXRULES is obsolete and should not be relied on, as:
@@ -191,8 +209,9 @@ UTF8_LOCALE=	en_US.utf8
 # On some hosts, this should have -lintl unless CFLAGS has -DHAVE_GETTEXT=0.
 LDLIBS=
 
-# Add the following to the end of the "CFLAGS=" line as needed to override
-# defaults specified in the source code.  "-DFOO" is equivalent to "-DFOO=1".
+# Add the following to an uncommented "CFLAGS=" line as needed
+# to override defaults specified in the source code or by the system.
+# "-DFOO" is equivalent to "-DFOO=1".
 #  -DDEPRECATE_TWO_DIGIT_YEARS for optional runtime warnings about strftime
 #	formats that generate only the last two digits of year numbers
 #  -DEPOCH_LOCAL if the 'time' function returns local time not UT
@@ -234,11 +253,16 @@ LDLIBS=
 #  -DHAVE_UNISTD_H=0 if <unistd.h> does not work*
 #  -DHAVE_UTMPX_H=0 if <utmpx.h> does not work*
 #  -Dlocale_t=XXX if your system uses XXX instead of locale_t
-#  -DPORT_TO_C89 if tzcode should also run on C89 platforms+
+#  -DPORT_TO_C89 if tzcode should also run on mostly-C89 platforms+
+#	Typically it is better to use a later standard.  For example,
+#	with GCC 4.9.4 (2016), prefer '-std=gnu11' to '-DPORT_TO_C89'.
+#	Even with -DPORT_TO_C89, the code needs at least one C99
+#	feature (integers at least 64 bits wide) and maybe more.
 #  -DRESERVE_STD_EXT_IDS if your platform reserves standard identifiers
 #	with external linkage, e.g., applications cannot define 'localtime'.
 #  -Dssize_t=long on hosts like MS-Windows that lack ssize_t
 #  -DSUPPORT_C89 if the tzcode library should support C89 callers+
+#	However, this might trigger latent bugs in C99-or-later callers.
 #  -DSUPPRESS_TZDIR to not prepend TZDIR to file names; this has
 #	security implications and is not recommended for general use
 #  -DTHREAD_SAFE to make localtime.c thread-safe, as POSIX requires;
@@ -250,7 +274,7 @@ LDLIBS=
 #  -DTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory;
 #	the default is system-supplied, typically "/usr/lib/locale"
 #  -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified
-#	DST transitions for POSIX-style TZ strings lacking them,
+#	DST transitions for POSIX.1-2017-style TZ strings lacking them,
 #	in the usual case where POSIXRULES is '-'.  If not specified,
 #	TZDEFRULESTRING defaults to US rules for future DST transitions.
 #	This mishandles some past timestamps, as US DST rules have changed.
@@ -270,11 +294,15 @@ LDLIBS=
 #  -DZIC_MAX_ABBR_LEN_WO_WARN=3
 #	(or some other number) to set the maximum time zone abbreviation length
 #	that zic will accept without a warning (the default is 6)
+#  -g to generate symbolic debugging info
+#  -Idir to include from directory 'dir'
+#  -O0 to disable optimization; other -O options to enable more optimization
+#  -Uname to remove any definition of the macro 'name'
 #  $(GCC_DEBUG_FLAGS) if you are using recent GCC and want lots of checking
 #
 # * Options marked "*" can be omitted if your compiler is C23 compatible.
 # * Options marked "+" are obsolescent and are planned to be removed
-#   once the code assumes C99 or later.
+#   once the code assumes C99 or later, say in the year 2029.
 #
 # Select instrumentation via "make GCC_INSTRUMENT='whatever'".
 GCC_INSTRUMENT = \
@@ -312,9 +340,10 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
 # guess TM_GMTOFF from other macros; define NO_TM_GMTOFF to suppress this.
 # Similarly, if your system has a "zone abbreviation" field, define
 #	-DTM_ZONE=tm_zone
-# and define NO_TM_ZONE to suppress any guessing.  Although these two fields
-# not required by POSIX, a future version of POSIX is planned to require them
-# and they are widely available on GNU/Linux and BSD systems.
+# and define NO_TM_ZONE to suppress any guessing.
+# Although these two fields are not required by POSIX.1-2017,
+# POSIX 202x/D4 requires them and they are widely available
+# on GNU/Linux and BSD systems.
 #
 # The next batch of options control support for external variables
 # exported by tzcode.  In practice these variables are less useful
@@ -324,7 +353,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
 # #	-DHAVE_TZNAME=0 # do not support "tzname"
 # #	-DHAVE_TZNAME=1 # support "tzname", which is defined by system library
 # #	-DHAVE_TZNAME=2 # support and define "tzname"
-# # to the "CFLAGS=" line.  "tzname" is required by POSIX 1988 and later.
+# # to the "CFLAGS=" line.  "tzname" is required by POSIX.1-1988 and later.
 # # If not defined, the code attempts to guess HAVE_TZNAME from other macros.
 # # Warning: unless time_tz is also defined, HAVE_TZNAME=1 can cause
 # # crashes when combined with some platforms' standard libraries,
@@ -334,8 +363,8 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
 # #	-DUSG_COMPAT=0 # do not support
 # #	-DUSG_COMPAT=1 # support, and variables are defined by system library
 # #	-DUSG_COMPAT=2 # support and define variables
-# # to the "CFLAGS=" line; "timezone" and "daylight" are inspired by
-# # Unix Systems Group code and are required by POSIX 2008 (with XSI) and later.
+# # to the "CFLAGS=" line; "timezone" and "daylight" are inspired by Unix
+# # Systems Group code and are required by POSIX.1-2008 and later (with XSI).
 # # If not defined, the code attempts to guess USG_COMPAT from other macros.
 # #
 # # To support the external variable "altzone", add
@@ -353,10 +382,11 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
 # functions to be added to the time conversion library.
 # "offtime" is like "gmtime" except that it accepts a second (long) argument
 # that gives an offset to add to the time_t when converting it.
-# "offtime_r" is to "offtime" what "gmtime_r" is to "gmtime".
-# "timelocal" is equivalent to "mktime".
+# I.e., "offtime" is like calling "localtime_rz" with a fixed-offset zone.
+# "timelocal" is nearly equivalent to "mktime".
 # "timeoff" is like "timegm" except that it accepts a second (long) argument
 # that gives an offset to use when converting to a time_t.
+# I.e., "timeoff" is like calling "mktime_z" with a fixed-offset zone.
 # "posix2time" and "time2posix" are described in an included manual page.
 # X3J11's work does not describe any of these functions.
 # These functions may well disappear in future releases of the time
@@ -379,7 +409,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
 #
 # NIST-PCTS:151-2, Version 1.4, (1993-12-03) is a test suite put
 # out by the National Institute of Standards and Technology
-# which claims to test C and Posix conformance.  If you want to pass PCTS, add
+# which claims to test C and POSIX conformance.  If you want to pass PCTS, add
 #	-DPCTS
 # to the end of the "CFLAGS=" line.
 #
@@ -389,19 +419,33 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
 # 53 as a week number (rather than 52 or 53) for January days before
 # January's first Monday when a "%V" format is used and January 1
 # falls on a Friday, Saturday, or Sunday.
+#
+# POSIX says CFLAGS defaults to "-O 1".
+# Uncomment the following line and edit its contents as needed.
 
-CFLAGS=
+#CFLAGS= -O 1
 
-# Linker flags.  Default to $(LFLAGS) for backwards compatibility
-# to release 2012h and earlier.
 
-LDFLAGS=	$(LFLAGS)
+# The name of a POSIX-like library archiver, its flags, C compiler,
+# linker flags, and 'make' utility.  Ordinarily the defaults suffice.
+# The commented-out values are the defaults specified by POSIX.1-202x/D4.
+#AR = ar
+#ARFLAGS = -rv
+#CC = c17
+#LDFLAGS =
+#MAKE = make
 
 # For leap seconds, this Makefile uses LEAPSECONDS='-L leapseconds' in
 # submake command lines.  The default is no leap seconds.
 
 LEAPSECONDS=
 
+# Where to fetch leap-seconds.list from.
+leaplist_URI = \
+  https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
+# The file is generated by the IERS Earth Orientation Centre, in Paris.
+leaplist_TZ = Europe/Paris
+
 # The zic command and its arguments.
 
 zic=		./zic
@@ -419,22 +463,23 @@ ZFLAGS=
 
 ZIC_INSTALL=	$(ZIC) -d '$(DESTDIR)$(TZDIR)' $(LEAPSECONDS)
 
-# The name of a Posix-compliant 'awk' on your system.
+# The name of a POSIX-compliant 'awk' on your system.
 # 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
+# The full path name of a POSIX-compliant shell, preferably one that supports
 # the Korn shell's 'select' statement as an extension.
 # These days, Bash is the most popular.
 # It should be OK to set this to /bin/sh, on platforms where /bin/sh
-# lacks 'select' or doesn't completely conform to Posix, but /bin/bash
+# lacks 'select' or doesn't completely conform to POSIX, but /bin/bash
 # is typically nicer if it works.
 KSHELL=		/bin/bash
 
-# Name of curl <https://curl.haxx.se/>, used for HTML validation.
+# Name of curl <https://curl.haxx.se/>, used for HTML validation
+# and to fetch leap-seconds.list from upstream.
 CURL=		curl
 
 # Name of GNU Privacy Guard <https://gnupg.org/>, used to sign distributions.
@@ -504,17 +549,16 @@ GZIPFLAGS=	-9n
 DIFF_TZS=	 diff -u$$(! diff -u -F'^TZ=' - - <>/dev/null >&0 2>&1 \
 			   || echo ' -F^TZ=')
 
-###############################################################################
-
-#MAKE=		make
+# ':' on typical hosts; 'ranlib' on the ancient hosts that still need ranlib.
+RANLIB=		:
 
-cc=		cc
-CC=		$(cc) -DTZDIR='"$(TZDIR)"'
+# POSIX prohibits defining or using SHELL.  However, csh users on systems
+# that use the user shell for Makefile commands may need to define SHELL.
+#SHELL=		/bin/sh
 
-AR=		ar
+# End of macros that one plausibly might want to tailor.
+###############################################################################
 
-# ':' on typical hosts; 'ranlib' on the ancient hosts that still need ranlib.
-RANLIB=		:
 
 TZCOBJS=	zic.o
 TZDOBJS=	zdump.o localtime.o asctime.o strftime.o
@@ -544,7 +588,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) \
@@ -552,7 +596,7 @@ TZDATA_ZI_DEPS=	ziguard.awk zishrink.awk version $(TDATA) \
 DSTDATA_ZI_DEPS= ziguard.awk $(TDATA) $(PACKRATDATA) $(PACKRATLIST)
 DATA=		$(TDATA_TO_CHECK) backzone iso3166.tab leap-seconds.list \
 			leapseconds $(ZONETABLES)
-AWK_SCRIPTS=	checklinks.awk checktab.awk leapseconds.awk \
+AWK_SCRIPTS=	checklinks.awk checknow.awk checktab.awk leapseconds.awk \
 			ziguard.awk zishrink.awk
 MISC=		$(AWK_SCRIPTS)
 TZS_YEAR=	2050
@@ -573,7 +617,7 @@ VERSION_DEPS= \
 		calendars CONTRIBUTING LICENSE Makefile NEWS README SECURITY \
 		africa antarctica asctime.c asia australasia \
 		backward backzone \
-		checklinks.awk checktab.awk \
+		checklinks.awk checknow.awk checktab.awk \
 		date.1 date.c difftime.c \
 		etcetera europe factory iso3166.tab \
 		leap-seconds.list leapseconds.awk localtime.c \
@@ -583,12 +627,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
-
-# And for the benefit of csh users on systems that assume the user
-# shell should be used to handle commands in Makefiles. . .
-
-SHELL=		/bin/sh
+		zone.tab zone1970.tab zonenow.tab
 
 all:		tzselect zic zdump libtz.a $(TABDATA) \
 		  vanguard.zi main.zi rearguard.zi
@@ -658,6 +697,16 @@ tzdata.zi:	$(DATAFORM).zi version zishrink.awk
 		    $(DATAFORM).zi >$@.out
 		mv $@.out $@
 
+tzdir.h:
+		printf '%s\n' >$@.out \
+		  '#ifndef TZDEFAULT' \
+		  '# define TZDEFAULT "$(TZDEFAULT)" /* default zone */' \
+		  '#endif' \
+		  '#ifndef TZDIR' \
+		  '# define TZDIR "$(TZDIR)" /* TZif directory */' \
+		  '#endif'
+		mv $@.out $@
+
 version.h:	version
 		VERSION=`cat version` && printf '%s\n' \
 		  'static char const PKGVERSION[]="($(PACKAGE)) ";' \
@@ -677,6 +726,28 @@ leapseconds:	$(LEAP_DEPS)
 		  -f leapseconds.awk leap-seconds.list >$@.out
 		mv $@.out $@
 
+# Awk script to extract a Git-style author from leap-seconds.list comments.
+EXTRACT_AUTHOR = \
+  author_line { sub(/^.[[:space:]]*/, ""); \
+      sub(/:[[:space:]]*/, " <"); \
+      printf "%s>\n", $$0; \
+      success = 1; \
+      exit \
+  } \
+  /Questions or comments to:/ { author_line = 1 } \
+  END { exit !success }
+
+# Fetch leap-seconds.list from upstream.
+fetch-leap-seconds.list:
+		$(CURL) -OR $(leaplist_URI)
+
+# Fetch leap-seconds.list from upstream and commit it to the local repository.
+commit-leap-seconds.list: fetch-leap-seconds.list
+		author=$$($(AWK) '$(EXTRACT_AUTHOR)' leap-seconds.list) && \
+		date=$$(TZ=$(leaplist_TZ) stat -c%y leap-seconds.list) && \
+		git commit --author="$$author" --date="$$date" -m'make $@' \
+		  leap-seconds.list
+
 # Arguments to pass to submakes of install_data.
 # They can be overridden by later submake arguments.
 INSTALLARGS = \
@@ -764,7 +835,7 @@ force_tzs:	$(TZS_NEW)
 
 libtz.a:	$(LIBOBJS)
 		rm -f $@
-		$(AR) -rc $@ $(LIBOBJS)
+		$(AR) $(ARFLAGS) $@ $(LIBOBJS)
 		$(RANLIB) $@
 
 date:		$(DATEOBJS)
@@ -772,26 +843,32 @@ date:		$(DATEOBJS)
 
 tzselect:	tzselect.ksh version
 		VERSION=`cat version` && sed \
-			-e 's|#!/bin/bash|#!$(KSHELL)|g' \
-			-e 's|AWK=[^}]*|AWK='\''$(AWK)'\''|g' \
-			-e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \
-			-e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \
-			-e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \
-			-e 's|\(TZVERSION\)=.*|\1='"$$VERSION"'|' \
-			<$@.ksh >$@.out
+		  -e "s'#!/bin/bash'#!"'$(KSHELL)'\' \
+		  -e s\''\(AWK\)=[^}]*'\''\1=\'\''$(AWK)\'\'\' \
+		  -e s\''\(PKGVERSION\)=.*'\''\1=\'\''($(PACKAGE)) \'\'\' \
+		  -e s\''\(REPORT_BUGS_TO\)=.*'\''\1=\'\''$(BUGEMAIL)\'\'\' \
+		  -e s\''\(TZDIR\)=[^}]*'\''\1=\'\''$(TZDIR)\'\'\' \
+		  -e s\''\(TZVERSION\)=.*'\''\1=\'"'$$VERSION\\''" \
+		  <$@.ksh >$@.out
 		chmod +x $@.out
 		mv $@.out $@
 
 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
 
+# True if UTF8_LOCALE does not work;
+# otherwise, false but with LC_ALL set to $(UTF8_LOCALE).
+UTF8_LOCALE_MISSING = \
+  { test ! '$(UTF8_LOCALE)' \
+    || ! printf 'A\304\200B\n' \
+         | LC_ALL='$(UTF8_LOCALE)' grep -q '^A.B$$' >/dev/null 2>&1 \
+    || { LC_ALL='$(UTF8_LOCALE)'; export LC_ALL; false; }; }
+
 check_character_set: $(ENCHILADA)
-	test ! '$(UTF8_LOCALE)' || \
-	! printf 'A\304\200B\n' | \
-	  LC_ALL='$(UTF8_LOCALE)' grep -q '^A.B$$' >/dev/null 2>&1 || { \
-		LC_ALL='$(UTF8_LOCALE)' && export LC_ALL && \
+	$(UTF8_LOCALE_MISSING) || { \
 		sharp='#' && \
 		! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \
 			$(MISC) $(SOURCES) $(WEB_PAGES) \
@@ -806,12 +883,12 @@ check_character_set: $(ENCHILADA)
 	touch $@
 
 check_white_space: $(ENCHILADA)
+	$(UTF8_LOCALE_MISSING) || { \
 		patfmt=' \t|[\f\r\v]' && pat=`printf "$$patfmt\\n"` && \
-		! grep -En "$$pat" \
-			$$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list)
-		! grep -n '[$s]$$' \
-			$$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list)
-		touch $@
+		! grep -En "$$pat|[$s]\$$" \
+			$$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list); \
+	}
+	touch $@
 
 PRECEDES_FILE_NAME = ^(Zone|Link[$s]+[^$s]+)[$s]+
 FILE_NAME_COMPONENT_TOO_LONG = $(PRECEDES_FILE_NAME)[^$s]*[^/$s]{15}
@@ -852,7 +929,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 \
@@ -912,10 +1011,10 @@ check_zishrink_posix check_zishrink_right: \
 		touch $@
 
 clean_misc:
-		rm -fr check_*.dir
+		rm -fr check_*.dir typecheck_*.dir
 		rm -f *.o *.out $(TIME_T_ALTERNATIVES) \
 		  check_* core typecheck_* \
-		  date tzselect version.h zdump zic libtz.a
+		  date tzdir.h tzselect version.h zdump zic libtz.a
 clean:		clean_misc
 		rm -fr *.dir tzdb-*/
 		rm -f *.zi $(TZS_NEW)
@@ -953,12 +1052,18 @@ $(MANTXTS):	workman.sh
 # plus N if GNU ls and touch are available.
 SET_TIMESTAMP_N = sh -c '\
   n=$$0 dest=$$1; shift; \
-  touch -cmr `ls -t "$$@" | sed 1q` "$$dest" && \
+  <"$$dest" && \
   if test $$n != 0 && \
-     lsout=`ls -n --time-style="+%s" "$$dest" 2>/dev/null`; then \
+     lsout=`ls -nt --time-style="+%s" "$$@" 2>/dev/null`; then \
     set x $$lsout && \
-    touch -cmd @`expr $$7 + $$n` "$$dest"; \
-  else :; fi'
+    timestamp=`expr $$7 + $$n` && \
+    echo "+ touch -md @$$timestamp $$dest" && \
+    touch -md @$$timestamp "$$dest"; \
+  else \
+    newest=`ls -t "$$@" | sed 1q` && \
+    echo "+ touch -mr $$newest $$dest" && \
+    touch -mr "$$newest" "$$dest"; \
+  fi'
 # If DEST depends on A B C ... in this Makefile, callers should use
 # $(SET_TIMESTAMP_DEP) DEST A B C ..., for the benefit of any
 # downstream 'make' that considers equal timestamps to be out of date.
@@ -983,8 +1088,12 @@ set-timestamps.out: $(EIGHT_YARDS)
 		  rm -f test.out && \
 		  for file in $$files; do \
 		    if git diff --quiet $$file; then \
-		      time=`git log -1 --format='tformat:%ct' $$file` && \
-		      touch -cmd @$$time $$file; \
+		      time=`TZ=UTC0 git log -1 \
+			--format='tformat:%cd' \
+			--date='format:%Y-%m-%dT%H:%M:%SZ' \
+			$$file` && \
+		      echo "+ touch -md $$time $$file" && \
+		      touch -md $$time $$file; \
 		    else \
 		      echo >&2 "$$file: warning: does not match repository"; \
 		    fi || exit; \
@@ -1009,7 +1118,8 @@ check_public: $(VERSION_DEPS)
 		rm -fr public.dir
 		mkdir public.dir
 		ln $(VERSION_DEPS) public.dir
-		cd public.dir && $(MAKE) CFLAGS='$(GCC_DEBUG_FLAGS)' ALL
+		cd public.dir \
+		  && $(MAKE) CFLAGS='$(GCC_DEBUG_FLAGS)' TZDIR='$(TZDIR)' ALL
 		for i in $(TDATA_TO_CHECK) public.dir/tzdata.zi \
 		    public.dir/vanguard.zi public.dir/main.zi \
 		    public.dir/rearguard.zi; \
@@ -1140,7 +1250,7 @@ tzdata$(VERSION)-rearguard.tar.gz: rearguard.zi set-timestamps.out
 		sed '1s/$$/-rearguard/' <version >$@.dir/version
 		: The dummy pacificnew pacifies TZUpdater 2.3.1 and earlier.
 		$(CREATE_EMPTY) $@.dir/pacificnew
-		touch -cmr version $@.dir/version
+		touch -mr version $@.dir/version
 		LC_ALL=C && export LC_ALL && \
 		  (cd $@.dir && \
 		   tar $(TARFLAGS) -cf - \
@@ -1164,7 +1274,7 @@ tzdata$(VERSION)-tailored.tar.gz: set-timestamps.out
 		  `test $(DATAFORM) = vanguard || echo pacificnew`
 		(grep '^#' tzdata.zi && echo && cat $(DATAFORM).zi) \
 		  >$@.dir/etcetera
-		touch -cmr tzdata.zi $@.dir/etcetera
+		touch -mr tzdata.zi $@.dir/etcetera
 		sed -n \
 		  -e '/^# *version  *\(.*\)/h' \
 		  -e '/^# *ddeps  */H' \
@@ -1175,7 +1285,7 @@ tzdata$(VERSION)-tailored.tar.gz: set-timestamps.out
 		  -e 's/ /-/g' \
 		  -e 'p' \
 		  <tzdata.zi >$@.dir/version
-		touch -cmr version $@.dir/version
+		touch -mr version $@.dir/version
 		links= && \
 		  for file in $(TZDATA_DIST); do \
 		    test -f $@.dir/$$file || links="$$links $$file"; \
@@ -1227,15 +1337,16 @@ zonenames:	tzdata.zi
 asctime.o:	private.h tzfile.h
 date.o:		private.h
 difftime.o:	private.h
-localtime.o:	private.h tzfile.h
+localtime.o:	private.h tzfile.h tzdir.h
 strftime.o:	private.h tzfile.h
 zdump.o:	version.h
-zic.o:		private.h tzfile.h version.h
+zic.o:		private.h tzfile.h tzdir.h version.h
 
 .PHONY: ALL INSTALL all
 .PHONY: check check_mild check_time_t_alternatives
 .PHONY: check_web check_zishrink
-.PHONY: clean clean_misc dummy.zd force_tzs
+.PHONY: clean clean_misc commit-leap-seconds.list dummy.zd
+.PHONY: fetch-leap-seconds.list force_tzs
 .PHONY: install install_data maintainer-clean names
 .PHONY: posix_only posix_right public
 .PHONY: rearguard_signatures rearguard_signatures_version
diff --git a/contrib/tzcode/NEWS b/contrib/tzcode/NEWS
index b54538aa4a82..d407342a50e6 100644
--- a/contrib/tzcode/NEWS
+++ b/contrib/tzcode/NEWS
@@ -1,5 +1,177 @@
 News for the tz database
 
+Release 2024a - 2024-02-01 09:28:56 -0800
+
+  Briefly:
+    Kazakhstan unifies on UTC+5 beginning 2024-03-01.
+    Palestine springs forward a week later after Ramadan.
+    zic no longer pretends to support indefinite-past DST.
+    localtime no longer mishandles Ciudad Juárez in 2422.
+
+  Changes to future timestamps
+
+    Kazakhstan unifies on UTC+5.  This affects Asia/Almaty and
+    Asia/Qostanay which together represent the eastern portion of the
+    country that will transition from UTC+6 on 2024-03-01 at 00:00 to
+    join the western portion.  (Thanks to Zhanbolat Raimbekov.)
+
+    Palestine springs forward a week later than previously predicted
+    in 2024 and 2025.  (Thanks to Heba Hamad.)  Change spring-forward
+    predictions to the second Saturday after Ramadan, not the first;
+    this also affects other predictions starting in 2039.
+
+  Changes to past timestamps
+
+    Asia/Ho_Chi_Minh's 1955-07-01 transition occurred at 01:00
+    not 00:00.  (Thanks to Đoàn Trần Công Danh.)
+
+    From 1947 through 1949, Toronto's transitions occurred at 02:00
+    not 00:00.  (Thanks to Chris Walton.)
+
+    In 1911 Miquelon adopted standard time on June 15, not May 15.
+
+  Changes to code
+
+    The FROM and TO columns of Rule lines can no longer be "minimum"
+    or an abbreviation of "minimum", because TZif files do not support
+    DST rules that extend into the indefinite past - although these
+    rules were supported when TZif files had only 32-bit data, this
+    stopped working when 64-bit TZif files were introduced in 1995.
+    This should not be a problem for realistic data, since DST was
+    first used in the 20th century.  As a transition aid, FROM columns
+    like "minimum" are now diagnosed and then treated as if they were
+    the year 1900; this should suffice for TZif files on old systems
+    with only 32-bit time_t, and it is more compatible with bugs in
+    2023c-and-earlier localtime.c.  (Problem reported by Yoshito
+    Umaoka.)
+
+    localtime and related functions no longer mishandle some
+    timestamps that occur about 400 years after a switch to a time
+    zone with a DST schedule.  In 2023d data this problem was visible
+    for some timestamps in November 2422, November 2822, etc. in
+    America/Ciudad_Juarez.  (Problem reported by Gilmore Davidson.)
+
+    strftime %s now uses tm_gmtoff if available.  (Problem and draft
+    patch reported by Dag-Erling Smørgrav.)
+
+  Changes to build procedure
+
+    The leap-seconds.list file is now copied from the IERS instead of
+    from its downstream counterpart at NIST, as the IERS version is
+    now in the public domain too and tends to be more up-to-date.
+    (Thanks to Martin Burnicki for liaisoning with the IERS.)
+
+  Changes to documentation
+
+    The strftime man page documents which struct tm members affect
+    which conversion specs, and that tzset is called.  (Problems
+    reported by Robert Elz and Steve Summit.)
+
+
+Release 2023d - 2023-12-21 20:02:24 -0800
+
+  Briefly:
+    Ittoqqortoormiit, Greenland changes time zones on 2024-03-31.
+    Vostok, Antarctica changed time zones on 2023-12-18.
+    Casey, Antarctica changed time zones five times since 2020.
+    Code and data fixes for Palestine timestamps starting in 2072.
+    A new data file zonenow.tab for timestamps starting now.
+
+  Changes to future timestamps
+
+    Ittoqqortoormiit, Greenland (America/Scoresbysund) joins most of
+    the rest of Greenland's timekeeping practice on 2024-03-31, by
+    changing its time zone from -01/+00 to -02/-01 at the same moment
+    as the spring-forward transition.  Its clocks will therefore not
+    spring forward as previously scheduled.  The time zone change
+    reverts to its common practice before 1981.
+
+    Fix predictions for DST transitions in Palestine in 2072-2075,
+    correcting a typo introduced in 2023a.
+
+  Changes to past and future timestamps
+
+    Vostok, Antarctica changed to +05 on 2023-12-18.  It had been at
+    +07 (not +06) for years.  (Thanks to Zakhary V. Akulov.)
+
+    Change data for Casey, Antarctica to agree with timeanddate.com,
+    by adding five time zone changes since 2020.  Casey is now at +08
+    instead of +11.
+
+  Changes to past tm_isdst flags
+
+    Much of Greenland, represented by America/Nuuk, changed its
+    standard time from -03 to -02 on 2023-03-25, not on 2023-10-28.
+    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.)
+
+    localtime.c's timeoff no longer collides with OpenBSD 7.4.
+
+    The C code now uses _Generic only if __STDC_VERSION__ says the
+    compiler is C11 or later.
+
+    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:
+
+      Spaces and most other special characters in BUGEMAIL, PACKAGE,
+      TZDIR, and VERSION.
+
+      TZ strings when using mawk 1.4.3, which mishandles regular
+      expressions of the form /X{2,}/.
+
+      ISO 6709 coordinates when using an awk that lacks the GNU
+      extension of newlines in -v option-arguments.
+
+      Non UTF-8 locales when using an iconv command that lacks the GNU
+      //TRANSLIT extension.
+
+    zic no longer mishandles data for Palestine after the year 2075.
+    Previously, it incorrectly omitted post-2075 transitions that are
+    predicted for just before and just after Ramadan.  (Thanks to Ken
+    Murchison for debugging help.)
+
+    zic now works again on Linux 2.6.16 and 2.6.17 (2006).
+    (Problem reported by Rune Torgersen.)
+
+  Changes to build procedure
+
+    The Makefile is now more compatible with POSIX:
+     * It no longer defines AR, CC, CFLAGS, LDFLAGS, and SHELL.
+     * It no longer uses its own 'cc' in place of CC.
+     * It now uses ARFLAGS, with default specified by POSIX.
+     * It does not use LFLAGS incompatibly with POSIX.
+     * It uses the special .POSIX target.
+     * It quotes special characters more carefully.
+     * It no longer mishandles builds in an ISO 8859 locale.
+    Due to the CC changes, TZDIR is now #defined in a file tzfile.h
+    built by 'make', not in a $(CC) -D option.  Also, TZDEFAULT is
+    now treated like TZDIR as they have similar roles.
+
+  Changes to commentary
+
+     Limitations and hazards of the optional support for obsolescent
+     C89 platforms are documented better, along with a tentative
+     schedule for removing this support.
+
+
 Release 2023c - 2023-03-28 12:42:14 -0700
 
   Changes to past and future timestamps
@@ -76,11 +248,14 @@ Release 2023a - 2023-03-22 12:39:33 -0700
     platform dependent and abbreviations were silently truncated to
     16 bytes even when the limit was greater than 16.
 
-    The code by default is now designed for C99 or later.  To build in
-    a C89 environment, compile with -DPORT_TO_C89.  To support C89
-    callers of the tzcode library, compile with -DSUPPORT_C89.  The
-    two new macros are transitional aids planned to be removed in a
-    future version, when C99 or later will be required.
+    The code by default is now designed for C99 or later.  To build on
+    a mostly-C89 platform, compile with -DPORT_TO_C89; this should
+    work on C89 platforms that also support C99 'long long' and
+    perhaps a few other extensions to C89.  To support C89 callers of
+    tzcode's library, compile with -DSUPPORT_C89; however, this could
+    trigger latent bugs in C99-or-later callers.  The two new macros
+    are transitional aids planned to be removed in a future version
+    (say, in 2029), when C99 or later will be required.
 
     The code now builds again on pre-C99 platforms, if you compile
     with -DPORT_TO_C89.  This fixes a bug introduced in 2022f.
@@ -723,6 +898,8 @@ Release 2021b - 2021-09-24 16:23:00 -0700
     them, set the EXPIRES_LINE Makefile variable.  If a TZif file uses
     this new feature it is marked with a new TZif version number 4,
     a format intended to be documented in a successor to RFC 8536.
+    The old-format "#expires" comments are now treated solely as
+    comments and have no effect on the TZif files.
 
     zic -L LEAPFILE -r @LO no longer generates an invalid TZif file
     that omits leap second information for the range LO..B when LO
@@ -4302,7 +4479,7 @@ Release 2012j - 2012-11-12 18:34:49 -0800
   now uses tz@iana.org rather than the old elsie address.
 
   zic -v now complains about abbreviations that are less than 3
-  or more than 6 characters, as per Posix.  Formerly, it checked
+  or more than 6 characters, as per POSIX.  Formerly, it checked
   for abbreviations that were more than 3.
 
   'make public' no longer puts its temporary directory under /tmp,
@@ -4467,8 +4644,8 @@ Release data2011m - 2011-10-24 21:42:16 +0700
   In particular, the typos in comments in the data (2011-11-17 should have
   been 2011-10-17 as Alan Barrett noted, and spelling of Tiraspol that
   Tim Parenti noted) have been fixed, and the change for Ukraine has been
-  made in all 4 Ukrainian zones, rather than just Kiev (again, thanks to
-  Tim Parenti, and also Denys Gavrysh)
+  made in all 4 Ukrainian zones, rather than just Europe/Kiev
+  (again, thanks to Tim Parenti, and also Denys Gavrysh).
 
   In addition, I added Europe/Tiraspol to zone.tab.
 
diff --git a/contrib/tzcode/README b/contrib/tzcode/README
index 145aacd495b7..edabd2e0690f 100644
--- a/contrib/tzcode/README
+++ b/contrib/tzcode/README
@@ -11,14 +11,17 @@ changes made by political bodies to time zone boundaries, UTC offsets,
 and daylight-saving rules.
 
 See <https://www.iana.org/time-zones/repository/tz-link.html> or the
-file tz-link.html for how to acquire the code and data.  Once acquired,
-read the comments in the file 'Makefile' and make any changes needed
-to make things right for your system, especially if you are using some
-platform other than GNU/Linux.  Then run the following commands,
-substituting your desired installation directory for "$HOME/tzdir":
-
-	make TOPDIR=$HOME/tzdir install
-	$HOME/tzdir/usr/bin/zdump -v America/Los_Angeles
+file tz-link.html for how to acquire the code and data.
+
+Once acquired, read the leading comments in the file "Makefile"
+and make any changes needed to make things right for your system,
+especially when using a platform other than current GNU/Linux.
+
+Then run the following commands, substituting your desired
+installation directory for "$HOME/tzdir":
+
+	make TOPDIR="$HOME/tzdir" install
+	"$HOME/tzdir/usr/bin/zdump" -v America/Los_Angeles
 
 See the file tz-how-to.html for examples of how to read the data files.
 
diff --git a/contrib/tzcode/date.1 b/contrib/tzcode/date.1
index e8107212364d..01907bc76e2c 100644
--- a/contrib/tzcode/date.1
+++ b/contrib/tzcode/date.1
@@ -154,15 +154,11 @@ hexadecimal (leading 0x), preceded by an optional sign.
 .br
 /usr/lib/locale/\f2L\fP/LC_TIME	description of time locale \f2L\fP
 .br
-/usr/share/zoneinfo	timezone information directory
+/usr/share/zoneinfo	timezone directory
 .br
-/usr/share/zoneinfo/posixrules	default DST rules (obsolete,
-	and can cause bugs if present)
+/usr/share/zoneinfo/posixrules	default DST rules (obsolete)
 .br
 /usr/share/zoneinfo/GMT	for UTC leap seconds
-.sp
-If
-.B /usr/share/zoneinfo/GMT
-is absent,
-UTC leap seconds are loaded from
-.BR /usr/share/zoneinfo/posixrules .
+.PP
+If /usr/share/zoneinfo/GMT is absent,
+UTC leap seconds are loaded from /usr/share/zoneinfo/GMT0 if present.
diff --git a/contrib/tzcode/localtime.c b/contrib/tzcode/localtime.c
index 3bf9378fe673..2b33cce1ec50 100644
--- a/contrib/tzcode/localtime.c
+++ b/contrib/tzcode/localtime.c
@@ -7,7 +7,7 @@
 
 /*
 ** Leap second handling from Bradley White.
-** POSIX-style TZ environment variable handling from Guy Harris.
+** POSIX.1-1988 style TZ environment variable handling from Guy Harris.
 */
 
 /*LINTLIBRARY*/
@@ -27,6 +27,7 @@
 #include "private.h"
 #include "un-namespace.h"
 
+#include "tzdir.h"
 #include "tzfile.h"
 
 #include "libc_private.h"
@@ -124,12 +125,17 @@ static char const UNSPEC[] = "-00";
    for ttunspecified to work without crashing.  */
 enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
 
-/* Limit to time zone abbreviation length in POSIX-style TZ strings.
+/* Limit to time zone abbreviation length in POSIX.1-2017-style TZ strings.
    This is distinct from TZ_MAX_CHARS, which limits TZif file contents.  */
 #ifndef TZNAME_MAXIMUM
 # define TZNAME_MAXIMUM 255
 #endif
 
+/* A representation of the contents of a TZif file.  Ideally this
+   would have no size limits; the following sizes should suffice for
+   practical use.  This struct should not be too large, as instances
+   are put on the stack and stacks are relatively small on some platforms.
+   See tzfile.h for more about the sizes.  */
 struct state {
 	int		leapcnt;
 	int		timecnt;
@@ -172,8 +178,7 @@ static int_fast32_t leapcorr(struct state const *, time_t);
 static bool normalize_overflow32(int_fast32_t *, int *, int);
 static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
 			  struct tm *);
-static bool typesequiv(struct state const *, int, int);
-static bool tzparse(char const *, struct state *, struct state *);
+static bool tzparse(char const *, struct state *, struct state const *);
 
 #ifdef ALL_STATE
 static struct state *	lclptr;
@@ -438,7 +443,8 @@ union input_buffer {
   /* The first part of the buffer, interpreted as a header.  */
   struct tzhead tzhead;
 
-  /* The entire buffer.  */
+  /* The entire buffer.  Ideally this would have no size limits;
+     the following should suffice for practical use.  */
   char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
 	   + 4 * TZ_MAX_TIMES];
 };
@@ -457,7 +463,12 @@ union local_storage {
     struct state st;
   } u;
 
-  /* The file name to be opened.  */
+  /* The name of the file to be opened.  Ideally this would have no
+     size limits, to support arbitrarily long Zone names.
+     Limiting Zone names to 1024 bytes should suffice for practical use.
+     However, there is no need for this to be smaller than struct
+     file_analysis as that struct is allocated anyway, as the other
+     union member.  */
   char fullname[max(sizeof(struct file_analysis), sizeof tzdirslash + 1024)];
 };
 
@@ -737,14 +748,18 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
 				       == sp->types[sp->timecnt - 2]))
 			      sp->timecnt--;
 
-			    for (i = 0;
-				 i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
-				 i++) {
+			    sp->goahead = ts->goahead;
+
+			    for (i = 0; i < ts->timecnt; i++) {
 			      time_t t = ts->ats[i];
 			      if (increment_overflow_time(&t, leapcorr(sp, t))
 				  || (0 < sp->timecnt
 				      && t <= sp->ats[sp->timecnt - 1]))
 				continue;
+			      if (TZ_MAX_TIMES <= sp->timecnt) {
+				sp->goahead = false;
+				break;
+			      }
 			      sp->ats[sp->timecnt] = t;
 			      sp->types[sp->timecnt] = (sp->typecnt
 							+ ts->types[i]);
@@ -757,28 +772,6 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
 	}
 	if (sp->typecnt == 0)
 	  return EINVAL;
-	if (sp->timecnt > 1) {
-	    if (sp->ats[0] <= TIME_T_MAX - SECSPERREPEAT) {
-		time_t repeatat = sp->ats[0] + SECSPERREPEAT;
-		int repeattype = sp->types[0];
-		for (i = 1; i < sp->timecnt; ++i)
-		  if (sp->ats[i] == repeatat
-		      && typesequiv(sp, sp->types[i], repeattype)) {
-					sp->goback = true;
-					break;
-		  }
-	    }
-	    if (TIME_T_MIN + SECSPERREPEAT <= sp->ats[sp->timecnt - 1]) {
-		time_t repeatat = sp->ats[sp->timecnt - 1] - SECSPERREPEAT;
-		int repeattype = sp->types[sp->timecnt - 1];
-		for (i = sp->timecnt - 2; i >= 0; --i)
-		  if (sp->ats[i] == repeatat
*** 3862 LINES SKIPPED ***