timezone: sync to TZDB 2024b

Sync tzselect, zdump, zic to TZDB 2024b. This patch incorporates the
following TZDB source code changes:

6903dde3 Release 2024b
812aff32 Improve historical transitions in Mexico 1921-1997
52662566 Adjust to mailing list software change
7748036b Mention Internet RFC 9557
339e81d1 Mention Levine’s proposal to replace leap seconds
b4e6ad2d No leap second on 2024-12-31
7eb5bf88 Asia/Choibalsan is now an alias for Asia/Ulaanbaatar
43450cbf Improve historical data for Portugal and former possessions.
13d7348b Typo and validation fixes.
3c39cde8 Fix typo for “removed” in a comment
03fd9e45 More documentation updates for POSIX.1-2024
eb3bcceb POSIX.1-2014 is now published
913b0410 tzselect: support POSIX.1-2024 offset range
b5318b55 Document POSIX.1-2024 better
837609b7 Fix typo when making .txt man pages
d56ae6ee SUPPORT_C89 now defaults to 1, not 0
b1fe113d Port ! to Solaris make
8f1fd321 Avoid crash in Solaris 10 /usr/xpg4/bin/make
e0fcfdd6 Use ‘export VAR=VAL’ syntax
eba43166 Avoid an awk invocation via $'...'
36479a80 Avoid some subshells in tzselect
7f6cf054 * tzselect.ksh: Assume POSIX.2 awk.
a1cf1daf * tzselect.ksh: Assume POSIX.2 $PWD.
a9b8e536 Assume POSIX.2 command substitution
eaa4ef16 Avoid subshells when possible
9dac9eb7 Prefer $PWD to $(pwd) in Makefile
fada6a4c Prefer $(CMD) to `CMD` in Makefile
3e871b9a Assume POSIX.2 and eschew ‘expr’
c5d67805 difftime isn’t pure either
5857c056 * CONTRIBUTING: Document build assumptions.
6822cc82 ‘make check’ no longer depends on curl+Internet
cc6eb255 Document GCC bug 114833 and workaround
bcbc86bf Scale back on function attribute use
c0789e46 C23 [[reproducible]] and [[unsequenced]] fixups
bbd88154 More updates to GCC_DEBUG_FLAGS for GCC 14
1a35b7c8 Spelling fixes
f71085f2 POSIX.1-2024 removes asctime_r, ctime_r
70856f8e Adjust to refactored location of ctime, ctime_r
aacd151d Update GCC_DEBUG_FLAGS for GCC 14
967dcf3b Sub-second history for Maputo and Zurich
782d0826 Make EET, MET and WET links
a0b09c02 Mark CET, CST6CDT etc. as obsolescent
db7fb40d Document SMPTE timecodes and rolling leaps
97232e18 Don’t be so sure about leap seconds going away
5b6a74fb Update some URLs
a75a6251 * zic.8: Tweak for consistency.
1e75b31f Document what %s means before any rule applies
00c96cbb Conform to RFC 8536 section 3.2 for default type
3e944959 Document problems with stripped-down TZif readers
20fc91cf Shanks is likely wrong about Maputo switch to CAT
d99589b6 * zic.8: Add missing tab character.
94e6b3b0 Switch to %z in main dataform
2cd57b93 Treat W-Eur like Port when reguarding
ad6f6d94 Check that main.zi agrees with sources
a43b030f .gitignore: Add .pdf, .ps, .s. Remove obsolete ‘yearistype’.
253ca020 * theory.html: ‘CLT’ → ‘LTC’ (per Michael H Deckers)
a3dee8c8 * NEWS: ‘how’ → ‘now’ (thanks to Paul Goyette).
ea6341c5 * theory.html: Mention NASA and CLT (per Arthur David Olson).
0dcebe37 America/Scoresbysund matches America/Nuuk from now on
b1e07fb0 Update Vzic link (thanks to Allen Winter)
a4b05030 Fix wday/mday typo in previous patch
732a4803 Document how to detect mktime failure reliably
a64067e9 ziguard.awk: generalize for proposed Portugal patch
59c861fd Line up zdump examples
66c106c9 tzfile.5: srcfix
e5553001 Fix .RS/.RE problem in tzfile.5
d647eb01 Add Doctorow book
59d4a1ba Asia/Almaty matches Asia/Tashkent from now on
d4d3c3ba * asia: Update Philippine URLs (thanks to Guy Harris).
9fc11a27 Port unlikely overflow check to C23
b52a2969 Fix 2023d NEWS typo
e48c5b53 Cite "The NTP Leap Second File"
b1dc2122 Update Israel tz-link
6cf4e912 Extrapolate less from the 2022 CGPM resolution.

It fixes glibc build with gcc master [1].

Checked on x86_64-linux-gnu and on i686-linux-gnu.

[1] https://sourceware.org/pipermail/libc-alpha/2024-September/159571.html
Reviewed-by: Paul Eggert <eggert@cs.ucla.edu>
This commit is contained in:
Adhemerval Zanella 2024-09-05 09:33:09 -03:00
parent a8c433856f
commit 1b171c942e
6 changed files with 151 additions and 142 deletions

View File

@ -180,9 +180,8 @@ unicode:
# The following files are shared with the upstream tzcode project and must be # The following files are shared with the upstream tzcode project and must be
# updated regularly to stay in sync with the upstream releases. # updated regularly to stay in sync with the upstream releases.
# #
# Currently synced to TZDB 2024a, announced and distributed here: # Currently synced to TZDB 2024b, announced and distributed here:
# https://mm.icann.org/pipermail/tz-announce/2024-February/000081.html # https://github.com/eggert/tz/releases/tag/2024b
# https://data.iana.org/time-zones/releases/tzdb-2024a.tar.lz
tzcode: tzcode:
timezone/private.h timezone/private.h
timezone/tzfile.h timezone/tzfile.h

View File

@ -19,19 +19,22 @@
/* PORT_TO_C89 means the code should work even if the underlying /* PORT_TO_C89 means the code should work even if the underlying
compiler and library support only C89 plus C99's 'long long' compiler and library support only C89 plus C99's 'long long'
and perhaps a few other extensions to C89. SUPPORT_C89 means the and perhaps a few other extensions to C89.
tzcode library should support C89 callers in addition to the usual
support for C99-and-later callers; however, C89 support can trigger This macro is obsolescent, and the plan is to remove it along with
latent bugs in C99-and-later callers. These macros are obsolescent, associated code. A good time to do that might be in the year 2029
and the plan is to remove them along with any code needed only when
they are nonzero. A good time to do that might be in the year 2029
because RHEL 7 (whose GCC defaults to C89) extended life cycle because RHEL 7 (whose GCC defaults to C89) extended life cycle
support (ELS) is scheduled to end on 2028-06-30. */ support (ELS) is scheduled to end on 2028-06-30. */
#ifndef PORT_TO_C89 #ifndef PORT_TO_C89
# define PORT_TO_C89 0 # define PORT_TO_C89 0
#endif #endif
/* SUPPORT_C89 means the tzcode library should support C89 callers
in addition to the usual support for C99-and-later callers.
This defaults to 1 as POSIX requires, even though that can trigger
latent bugs in callers. */
#ifndef SUPPORT_C89 #ifndef SUPPORT_C89
# define SUPPORT_C89 0 # define SUPPORT_C89 1
#endif #endif
#ifndef __STDC_VERSION__ #ifndef __STDC_VERSION__
@ -69,10 +72,6 @@
** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'. ** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
*/ */
#ifndef HAVE_DECL_ASCTIME_R
# define HAVE_DECL_ASCTIME_R 1
#endif
#if !defined HAVE__GENERIC && defined __has_extension #if !defined HAVE__GENERIC && defined __has_extension
# if !__has_extension(c_generic_selections) # if !__has_extension(c_generic_selections)
# define HAVE__GENERIC 0 # define HAVE__GENERIC 0
@ -236,6 +235,31 @@
# include <unistd.h> /* for R_OK, and other POSIX goodness */ # include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */
/* SUPPORT_POSIX2008 means the tzcode library should support
POSIX.1-2017-and-earlier callers in addition to the usual support for
POSIX.1-2024-and-later callers; however, this can be
incompatible with POSIX.1-2024-and-later callers.
This macro is obsolescent, and the plan is to remove it
along with any code needed only when it is nonzero.
A good time to do that might be in the year 2034.
This macro's name is SUPPORT_POSIX2008 because _POSIX_VERSION == 200809
in POSIX.1-2017, a minor revision of POSIX.1-2008. */
#ifndef SUPPORT_POSIX2008
# if defined _POSIX_VERSION && _POSIX_VERSION <= 200809
# define SUPPORT_POSIX2008 1
# else
# define SUPPORT_POSIX2008 0
# endif
#endif
#ifndef HAVE_DECL_ASCTIME_R
# if SUPPORT_POSIX2008
# define HAVE_DECL_ASCTIME_R 1
# else
# define HAVE_DECL_ASCTIME_R 0
# endif
#endif
#ifndef HAVE_STRFTIME_L #ifndef HAVE_STRFTIME_L
# if _POSIX_VERSION < 200809 # if _POSIX_VERSION < 200809
# define HAVE_STRFTIME_L 0 # define HAVE_STRFTIME_L 0
@ -460,14 +484,6 @@ typedef unsigned long uintmax_t;
# define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r) # define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
#endif #endif
#if 3 <= __GNUC__
# define ATTRIBUTE_MALLOC __attribute__((malloc))
# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec))
#else
# define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if (defined __has_c_attribute \ #if (defined __has_c_attribute \
&& (202311 <= __STDC_VERSION__ || !defined __STRICT_ANSI__)) && (202311 <= __STDC_VERSION__ || !defined __STRICT_ANSI__))
# define HAVE___HAS_C_ATTRIBUTE true # define HAVE___HAS_C_ATTRIBUTE true
@ -535,24 +551,27 @@ typedef unsigned long uintmax_t;
# endif # endif
#endif #endif
#ifndef ATTRIBUTE_REPRODUCIBLE #ifndef ATTRIBUTE_REPRODUCIBLE
# if 3 <= __GNUC__
# define ATTRIBUTE_REPRODUCIBLE __attribute__((pure))
# else
# define ATTRIBUTE_REPRODUCIBLE /* empty */ # define ATTRIBUTE_REPRODUCIBLE /* empty */
#endif #endif
/* GCC attributes that are useful in tzcode.
__attribute__((pure)) is stricter than [[reproducible]],
so the latter is an adequate substitute in non-GCC C23 platforms. */
#if __GNUC__ < 3
# define ATTRIBUTE_FORMAT(spec) /* empty */
# define ATTRIBUTE_PURE ATTRIBUTE_REPRODUCIBLE
#else
# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec))
# define ATTRIBUTE_PURE __attribute__((pure))
#endif #endif
#if HAVE___HAS_C_ATTRIBUTE /* Avoid GCC bug 114833 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114833>.
# if __has_c_attribute(unsequenced) Remove this macro and its uses when the bug is fixed in a GCC release,
# define ATTRIBUTE_UNSEQUENCED [[unsequenced]] because only the latest GCC matters for $(GCC_DEBUG_FLAGS). */
# endif #ifdef GCC_LINT
#endif # define ATTRIBUTE_PURE_114833 ATTRIBUTE_PURE
#ifndef ATTRIBUTE_UNSEQUENCED
# if 3 <= __GNUC__
# define ATTRIBUTE_UNSEQUENCED __attribute__((const))
#else #else
# define ATTRIBUTE_UNSEQUENCED /* empty */ # define ATTRIBUTE_PURE_114833 /* empty */
# endif
#endif #endif
#if (__STDC_VERSION__ < 199901 && !defined restrict \ #if (__STDC_VERSION__ < 199901 && !defined restrict \
@ -604,12 +623,8 @@ typedef time_tz tz_time_t;
# undef asctime # undef asctime
# define asctime tz_asctime # define asctime tz_asctime
# undef asctime_r
# define asctime_r tz_asctime_r
# undef ctime # undef ctime
# define ctime tz_ctime # define ctime tz_ctime
# undef ctime_r
# define ctime_r tz_ctime_r
# undef difftime # undef difftime
# define difftime tz_difftime # define difftime tz_difftime
# undef gmtime # undef gmtime
@ -654,6 +669,12 @@ typedef time_tz tz_time_t;
# define tzfree tz_tzfree # define tzfree tz_tzfree
# undef tzset # undef tzset
# define tzset tz_tzset # define tzset tz_tzset
# if SUPPORT_POSIX2008
# undef asctime_r
# define asctime_r tz_asctime_r
# undef ctime_r
# define ctime_r tz_ctime_r
# endif
# if HAVE_STRFTIME_L # if HAVE_STRFTIME_L
# undef strftime_l # undef strftime_l
# define strftime_l tz_strftime_l # define strftime_l tz_strftime_l
@ -679,10 +700,12 @@ typedef time_tz tz_time_t;
# define DEPRECATED_IN_C23 ATTRIBUTE_DEPRECATED # define DEPRECATED_IN_C23 ATTRIBUTE_DEPRECATED
# endif # endif
DEPRECATED_IN_C23 char *asctime(struct tm const *); DEPRECATED_IN_C23 char *asctime(struct tm const *);
char *asctime_r(struct tm const *restrict, char *restrict);
DEPRECATED_IN_C23 char *ctime(time_t const *); DEPRECATED_IN_C23 char *ctime(time_t const *);
#if SUPPORT_POSIX2008
char *asctime_r(struct tm const *restrict, char *restrict);
char *ctime_r(time_t const *, char *); char *ctime_r(time_t const *, char *);
ATTRIBUTE_UNSEQUENCED double difftime(time_t, time_t); #endif
double difftime(time_t, time_t);
size_t strftime(char *restrict, size_t, char const *restrict, size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict); struct tm const *restrict);
# if HAVE_STRFTIME_L # if HAVE_STRFTIME_L
@ -713,7 +736,7 @@ void tzset(void);
time_t timegm(struct tm *); time_t timegm(struct tm *);
#endif #endif
#if !HAVE_DECL_ASCTIME_R && !defined asctime_r #if !HAVE_DECL_ASCTIME_R && !defined asctime_r && SUPPORT_POSIX2008
extern char *asctime_r(struct tm const *restrict, char *restrict); extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif #endif
@ -798,10 +821,10 @@ timezone_t tzalloc(char const *);
void tzfree(timezone_t); void tzfree(timezone_t);
# if STD_INSPIRED # if STD_INSPIRED
# if TZ_TIME_T || !defined posix2time_z # if TZ_TIME_T || !defined posix2time_z
ATTRIBUTE_REPRODUCIBLE time_t posix2time_z(timezone_t, time_t); ATTRIBUTE_PURE time_t posix2time_z(timezone_t, time_t);
# endif # endif
# if TZ_TIME_T || !defined time2posix_z # if TZ_TIME_T || !defined time2posix_z
ATTRIBUTE_REPRODUCIBLE time_t time2posix_z(timezone_t, time_t); ATTRIBUTE_PURE time_t time2posix_z(timezone_t, time_t);
# endif # endif
# endif # endif
#endif #endif
@ -973,8 +996,9 @@ enum {
/* How many years to generate (in zic.c) or search through (in localtime.c). /* How many years to generate (in zic.c) or search through (in localtime.c).
This is two years larger than the obvious 400, to avoid edge cases. This is two years larger than the obvious 400, to avoid edge cases.
E.g., suppose a non-POSIX.1-2017 rule applies from 2012 on with transitions E.g., suppose a rule applies from 2012 on with transitions
in March and September, plus one-off transitions in November 2013. in March and September, plus one-off transitions in November 2013,
and suppose the rule cannot be expressed as a proleptic TZ string.
If zic looked only at the last 400 years, it would set max_year=2413, If zic looked only at the last 400 years, it would set max_year=2413,
with the intent that the 400 years 2014 through 2413 will be repeated. with the intent that the 400 years 2014 through 2413 will be repeated.
The last transition listed in the tzfile would be in 2413-09, The last transition listed in the tzfile would be in 2413-09,

View File

@ -76,14 +76,16 @@ struct tzhead {
** If tzh_version is '2' or greater, the above is followed by a second instance ** If tzh_version is '2' or greater, the above is followed by a second instance
** of tzhead and a second instance of the data in which each coded transition ** of tzhead and a second instance of the data in which each coded transition
** time uses 8 rather than 4 chars, ** time uses 8 rather than 4 chars,
** then a POSIX-TZ-environment-variable-style string for use in handling ** then a POSIX.1-2017 proleptic TZ string for use in handling
** instants after the last transition time stored in the file ** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX.1-2017 ** (with nothing between the newlines if there is no POSIX.1-2017
** representation for such instants). ** representation for such instants).
** **
** If tz_version is '3' or greater, the above is extended as follows. ** If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024
** proleptic TZ string, which means the above is extended as follows.
** First, the TZ string's hour offset may range from -167 ** First, the TZ string's hour offset may range from -167
** through 167 as compared to the POSIX-required 0 through 24. ** through 167 as compared to the range 0 through 24 required
** by POSIX.1-2017 and earlier.
** Second, its DST start time may be January 1 at 00:00 and its stop ** Second, its DST start time may be January 1 at 00:00 and its stop
** time December 31 at 24:00 plus the difference between DST and ** time December 31 at 24:00 plus the difference between DST and
** standard time, indicating DST all year. ** standard time, indicating DST all year.

View File

@ -20,12 +20,6 @@ REPORT_BUGS_TO=tz@iana.org
# Korn Shell <http://www.kornshell.com/> # Korn Shell <http://www.kornshell.com/>
# MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm> # MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm>
# #
# For portability to Solaris 10 /bin/sh (supported by Oracle through
# January 2027) this script avoids some POSIX features and common
# extensions, such as $(...), $((...)), ! CMD, unquoted ^, ${#ID},
# ${ID##PAT}, ${ID%%PAT}, and $10. Although some of these constructs
# work sometimes, it's simpler to avoid them entirely.
#
# This script also uses several features of POSIX awk. # This script also uses several features of POSIX awk.
# If your host lacks awk, or has an old awk that does not conform to POSIX, # If your host lacks awk, or has an old awk that does not conform to POSIX,
# you can use any of the following free programs instead: # you can use any of the following free programs instead:
@ -45,7 +39,6 @@ set -f
# Specify default values for environment variables if they are unset. # Specify default values for environment variables if they are unset.
: ${AWK=awk} : ${AWK=awk}
: ${PWD=`pwd`}
: ${TZDIR=$PWD} : ${TZDIR=$PWD}
# Output one argument as-is to standard output, with trailing newline. # Output one argument as-is to standard output, with trailing newline.
@ -54,13 +47,6 @@ say() {
printf '%s\n' "$1" printf '%s\n' "$1"
} }
# Check for awk POSIX compliance.
($AWK -v x=y 'BEGIN { exit 123 }') <>/dev/null >&0 2>&0
[ $? = 123 ] || {
say >&2 "$0: Sorry, your '$AWK' program is not POSIX compatible."
exit 1
}
coord= coord=
location_limit=10 location_limit=10
zonetabtype=zone1970 zonetabtype=zone1970
@ -117,8 +103,7 @@ then
else else
doselect() { doselect() {
# Field width of the prompt numbers. # Field width of the prompt numbers.
print_nargs_length="BEGIN {print length(\"$#\");}" select_width=${##}
select_width=`$AWK "$print_nargs_length"`
select_i= select_i=
@ -129,14 +114,14 @@ else
select_i=0 select_i=0
for select_word for select_word
do do
select_i=`$AWK "BEGIN { print $select_i + 1 }"` select_i=$(($select_i + 1))
printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word" printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word"
done;; done;;
*[!0-9]*) *[!0-9]*)
echo >&2 'Please enter a number in range.';; echo >&2 'Please enter a number in range.';;
*) *)
if test 1 -le $select_i && test $select_i -le $#; then if test 1 -le $select_i && test $select_i -le $#; then
shift `$AWK "BEGIN { print $select_i - 1 }"` shift $(($select_i - 1))
select_result=$1 select_result=$1
break break
fi fi
@ -170,7 +155,7 @@ do
esac esac
done done
shift `$AWK "BEGIN { print $OPTIND - 1 }"` shift $(($OPTIND - 1))
case $# in case $# in
0) ;; 0) ;;
*) say >&2 "$0: $1: unknown argument"; exit 1 *) say >&2 "$0: $1: unknown argument"; exit 1
@ -178,11 +163,13 @@ esac
# translit=true to try transliteration. # translit=true to try transliteration.
# This is false if U+12345 CUNEIFORM SIGN URU TIMES KI has length 1 # This is false if U+12345 CUNEIFORM SIGN URU TIMES KI has length 1
# which means awk (and presumably the shell) do not need transliteration. # which means the shell and (presumably) awk do not need transliteration.
if $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) == 1 }'; then # It is true if the byte string has some other length in characters, or
translit=true # if this is a POSIX.1-2017 or earlier shell that does not support $'...'.
else CUNEIFORM_SIGN_URU_TIMES_KI=$'\360\222\215\205'
translit=false if test ${#CUNEIFORM_SIGN_URU_TIMES_KI} = 1
then translit=false
else translit=true
fi fi
# Read into shell variable $1 the contents of file $2. # Read into shell variable $1 the contents of file $2.
@ -192,10 +179,10 @@ fi
# if that does not work, fall back on 'cat'. # if that does not work, fall back on 'cat'.
read_file() { read_file() {
{ $translit && { { $translit && {
eval "$1=\`(iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\"\`" || eval "$1=\$( (iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\")" ||
eval "$1=\`(iconv -f UTF-8) 2>/dev/null <\"\$2\"\`" eval "$1=\$( (iconv -f UTF-8) 2>/dev/null <\"\$2\")"
}; } || }; } ||
eval "$1=\`cat <\"\$2\"\`" || { eval "$1=\$(cat <\"\$2\")" || {
say >&2 "$0: time zone files are not set up correctly" say >&2 "$0: time zone files are not set up correctly"
exit 1 exit 1
} }
@ -403,7 +390,7 @@ while
echo >&2 \ echo >&2 \
'Please select a continent, ocean, "coord", "TZ", "time", or "now".' 'Please select a continent, ocean, "coord", "TZ", "time", or "now".'
quoted_continents=` quoted_continents=$(
$AWK ' $AWK '
function handle_entry(entry) { function handle_entry(entry) {
entry = substr(entry, 1, index(entry, "/") - 1) entry = substr(entry, 1, index(entry, "/") - 1)
@ -433,12 +420,12 @@ while
sort -u | sort -u |
tr '\n' ' ' tr '\n' ' '
echo '' echo ''
` )
eval ' eval '
doselect '"$quoted_continents"' \ doselect '"$quoted_continents"' \
"coord - I want to use geographical coordinates." \ "coord - I want to use geographical coordinates." \
"TZ - I want to specify the timezone using a POSIX.1-2017 TZ string." \ "TZ - I want to specify the timezone using a proleptic TZ string." \
"time - I know local time already." \ "time - I know local time already." \
"now - Like \"time\", but configure only for timestamps from now on." "now - Like \"time\", but configure only for timestamps from now on."
continent=$select_result continent=$select_result
@ -462,16 +449,17 @@ while
case $continent in case $continent in
TZ) TZ)
# Ask the user for a POSIX.1-2017 TZ string. Check that it conforms. # Ask the user for a proleptic TZ string. Check that it conforms.
check_POSIX_TZ_string=' check_POSIX_TZ_string='
BEGIN { BEGIN {
tz = substr(ARGV[1], 2) tz = substr(ARGV[1], 2)
ARGV[1] = "" ARGV[1] = ""
tzname = ("(<[[:alnum:]+-][[:alnum:]+-][[:alnum:]+-]+>" \ tzname = ("(<[[:alnum:]+-][[:alnum:]+-][[:alnum:]+-]+>" \
"|[[:alpha:]][[:alpha:]][[:alpha:]]+)") "|[[:alpha:]][[:alpha:]][[:alpha:]]+)")
time = ("(2[0-4]|[0-1]?[0-9])" \ sign = "[-+]?"
"(:[0-5][0-9](:[0-5][0-9])?)?") hhmm = "(:[0-5][0-9](:[0-5][0-9])?)?"
offset = "[-+]?" time offset = sign "(2[0-4]|[0-1]?[0-9])" hhmm
time = sign "(16[0-7]|(1[0-5]|[0-9]?)[0-9])" hhmm
mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]" mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]"
jdate = ("((J[1-9]|[0-9]|J?[1-9][0-9]" \ jdate = ("((J[1-9]|[0-9]|J?[1-9][0-9]" \
"|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])") "|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])")
@ -492,7 +480,7 @@ while
read tz read tz
$AWK "$check_POSIX_TZ_string" ="$tz" $AWK "$check_POSIX_TZ_string" ="$tz"
do do
say >&2 "'$tz' is not a conforming POSIX.1-2017 timezone string." say >&2 "'$tz' is not a conforming POSIX proleptic TZ string."
done done
TZ_for_date=$tz;; TZ_for_date=$tz;;
*) *)
@ -507,14 +495,14 @@ while
'74 degrees 3 minutes west.' '74 degrees 3 minutes west.'
read coord read coord
esac esac
distance_table=` distance_table=$(
$AWK \ $AWK \
"$output_distances_or_times" \ "$output_distances_or_times" \
="$coord" ="$TZ_COUNTRY_TABLE" ="$TZ_ZONE_TABLE" | ="$coord" ="$TZ_COUNTRY_TABLE" ="$TZ_ZONE_TABLE" |
sort -n | sort -n |
$AWK "{print} NR == $location_limit { exit }" $AWK "{print} NR == $location_limit { exit }"
` )
regions=` regions=$(
$AWK ' $AWK '
BEGIN { BEGIN {
distance_table = substr(ARGV[1], 2) distance_table = substr(ARGV[1], 2)
@ -526,13 +514,13 @@ while
} }
} }
' ="$distance_table" ' ="$distance_table"
` )
echo >&2 'Please select one of the following timezones,' echo >&2 'Please select one of the following timezones,'
echo >&2 'listed roughly in increasing order' \ echo >&2 'listed roughly in increasing order' \
"of distance from $coord". "of distance from $coord".
doselect $regions doselect $regions
region=$select_result region=$select_result
tz=` tz=$(
$AWK ' $AWK '
BEGIN { BEGIN {
distance_table = substr(ARGV[1], 2) distance_table = substr(ARGV[1], 2)
@ -546,22 +534,22 @@ while
} }
} }
' ="$distance_table" ="$region" ' ="$distance_table" ="$region"
`;; );;
*) *)
case $continent in case $continent in
now|time) now|time)
minute_format='%a %b %d %H:%M' minute_format='%a %b %d %H:%M'
old_minute=`TZ=UTC0 date +"$minute_format"` old_minute=$(TZ=UTC0 date +"$minute_format")
for i in 1 2 3 for i in 1 2 3
do do
time_table_command=` time_table_command=$(
$AWK \ $AWK \
-v output_times=1 \ -v output_times=1 \
"$output_distances_or_times" \ "$output_distances_or_times" \
= = ="$TZ_ZONE_TABLE" = = ="$TZ_ZONE_TABLE"
` )
time_table=`eval "$time_table_command"` time_table=$(eval "$time_table_command")
new_minute=`TZ=UTC0 date +"$minute_format"` new_minute=$(TZ=UTC0 date +"$minute_format")
case $old_minute in case $old_minute in
"$new_minute") break "$new_minute") break
esac esac
@ -569,11 +557,11 @@ while
done done
echo >&2 "The system says Universal Time is $new_minute." echo >&2 "The system says Universal Time is $new_minute."
echo >&2 "Assuming that's correct, what is the local time?" echo >&2 "Assuming that's correct, what is the local time?"
sorted_table=`say "$time_table" | sort -k2n -k2,5 -k1n` || { sorted_table=$(say "$time_table" | sort -k2n -k2,5 -k1n) || {
say >&2 "$0: cannot sort time table" say >&2 "$0: cannot sort time table"
exit 1 exit 1
} }
eval doselect ` eval doselect $(
$AWK ' $AWK '
BEGIN { BEGIN {
sorted_table = substr(ARGV[1], 2) sorted_table = substr(ARGV[1], 2)
@ -590,10 +578,10 @@ while
} }
} }
' ="$sorted_table" ' ="$sorted_table"
` )
time=$select_result time=$select_result
continent_re='^' continent_re='^'
zone_table=` zone_table=$(
$AWK ' $AWK '
BEGIN { BEGIN {
time = substr(ARGV[1], 2) time = substr(ARGV[1], 2)
@ -609,13 +597,13 @@ while
} }
} }
' ="$time" ="$time_table" ' ="$time" ="$time_table"
` )
countries=` countries=$(
$AWK \ $AWK \
"$output_country_list" \ "$output_country_list" \
="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" |
sort -f sort -f
` )
;; ;;
*) *)
continent_re="^$continent/" continent_re="^$continent/"
@ -623,16 +611,16 @@ while
esac esac
# Get list of names of countries in the continent or ocean. # Get list of names of countries in the continent or ocean.
countries=` countries=$(
$AWK \ $AWK \
"$output_country_list" \ "$output_country_list" \
="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" |
sort -f sort -f
` )
# If all zone table entries have comments, and there are # If all zone table entries have comments, and there are
# at most 22 entries, asked based on those comments. # at most 22 entries, asked based on those comments.
# This fits the prompt onto old-fashioned 24-line screens. # This fits the prompt onto old-fashioned 24-line screens.
regions=` regions=$(
$AWK ' $AWK '
BEGIN { BEGIN {
TZ_ZONE_TABLE = substr(ARGV[1], 2) TZ_ZONE_TABLE = substr(ARGV[1], 2)
@ -653,7 +641,7 @@ while
print comment[i] print comment[i]
} }
' ="$zone_table" ' ="$zone_table"
` )
# If there's more than one country, ask the user which one. # If there's more than one country, ask the user which one.
case $countries in case $countries in
@ -669,7 +657,7 @@ while
# Get list of timezones in the country. # Get list of timezones in the country.
regions=` regions=$(
$AWK ' $AWK '
BEGIN { BEGIN {
country = substr(ARGV[1], 2) country = substr(ARGV[1], 2)
@ -696,7 +684,7 @@ while
} }
} }
' ="$country" ="$TZ_COUNTRY_TABLE" ="$zone_table" ' ="$country" ="$TZ_COUNTRY_TABLE" ="$zone_table"
` )
# If there's more than one region, ask the user which one. # If there's more than one region, ask the user which one.
case $regions in case $regions in
@ -707,7 +695,7 @@ while
esac esac
# Determine tz from country and region. # Determine tz from country and region.
tz=` tz=$(
$AWK ' $AWK '
BEGIN { BEGIN {
country = substr(ARGV[1], 2) country = substr(ARGV[1], 2)
@ -735,7 +723,7 @@ while
} }
} }
' ="$country" ="$region" ="$TZ_COUNTRY_TABLE" ="$zone_table" ' ="$country" ="$region" ="$TZ_COUNTRY_TABLE" ="$zone_table"
` )
esac esac
# Make sure the corresponding zoneinfo file exists. # Make sure the corresponding zoneinfo file exists.
@ -754,14 +742,11 @@ while
extra_info= extra_info=
for i in 1 2 3 4 5 6 7 8 for i in 1 2 3 4 5 6 7 8
do do
TZdate=`LANG=C TZ="$TZ_for_date" date` TZdate=$(LANG=C TZ="$TZ_for_date" date)
UTdate=`LANG=C TZ=UTC0 date` UTdate=$(LANG=C TZ=UTC0 date)
if $AWK ' TZsecsetc=${TZdate##*[0-5][0-9]:}
function getsecs(d) { UTsecsetc=${UTdate##*[0-5][0-9]:}
return match(d, /.*:[0-5][0-9]/) ? substr(d, RLENGTH - 1, 2) : "" if test "${TZsecsetc%%[!0-9]*}" = "${UTsecsetc%%[!0-9]*}"
}
BEGIN { exit getsecs(ARGV[1]) != getsecs(ARGV[2]) }
' ="$TZdate" ="$UTdate"
then then
extra_info=" extra_info="
Selected time is now: $TZdate. Selected time is now: $TZdate.
@ -801,7 +786,7 @@ done
case $SHELL in case $SHELL in
*csh) file=.login line="setenv TZ '$tz'";; *csh) file=.login line="setenv TZ '$tz'";;
*) file=.profile line="TZ='$tz'; export TZ" *) file=.profile line="export TZ='$tz'"
esac esac
test -t 1 && say >&2 " test -t 1 && say >&2 "

View File

@ -89,7 +89,7 @@ static bool warned;
static bool errout; static bool errout;
static char const *abbr(struct tm const *); static char const *abbr(struct tm const *);
ATTRIBUTE_REPRODUCIBLE static intmax_t delta(struct tm *, struct tm *); static intmax_t delta(struct tm *, struct tm *);
static void dumptime(struct tm const *); static void dumptime(struct tm const *);
static time_t hunt(timezone_t, time_t, time_t, bool); static time_t hunt(timezone_t, time_t, time_t, bool);
static void show(timezone_t, char *, time_t, bool); static void show(timezone_t, char *, time_t, bool);
@ -97,7 +97,7 @@ static void showextrema(timezone_t, char *, time_t, struct tm *, time_t);
static void showtrans(char const *, struct tm const *, time_t, char const *, static void showtrans(char const *, struct tm const *, time_t, char const *,
char const *); char const *);
static const char *tformat(void); static const char *tformat(void);
ATTRIBUTE_REPRODUCIBLE static time_t yeartot(intmax_t); ATTRIBUTE_PURE_114833 static time_t yeartot(intmax_t);
/* Is C an ASCII digit? */ /* Is C an ASCII digit? */
static bool static bool
@ -134,7 +134,7 @@ size_overflow(void)
/* Return A + B, exiting if the result would overflow either ptrdiff_t /* Return A + B, exiting if the result would overflow either ptrdiff_t
or size_t. A and B are both nonnegative. */ or size_t. A and B are both nonnegative. */
ATTRIBUTE_REPRODUCIBLE static ptrdiff_t ATTRIBUTE_PURE_114833 static ptrdiff_t
sumsize(ptrdiff_t a, ptrdiff_t b) sumsize(ptrdiff_t a, ptrdiff_t b)
{ {
#ifdef ckd_add #ifdef ckd_add
@ -162,7 +162,7 @@ xstrsize(char const *str)
/* Return a pointer to a newly allocated buffer of size SIZE, exiting /* Return a pointer to a newly allocated buffer of size SIZE, exiting
on failure. SIZE should be positive. */ on failure. SIZE should be positive. */
ATTRIBUTE_MALLOC static void * static void *
xmalloc(ptrdiff_t size) xmalloc(ptrdiff_t size)
{ {
void *p = malloc(size); void *p = malloc(size);
@ -932,7 +932,7 @@ showextrema(timezone_t tz, char *zone, time_t lo, struct tm *lotmp, time_t hi)
# include <stdarg.h> # include <stdarg.h>
/* A substitute for snprintf that is good enough for zdump. */ /* A substitute for snprintf that is good enough for zdump. */
ATTRIBUTE_FORMAT((printf, 3, 4)) static int static int
my_snprintf(char *s, size_t size, char const *format, ...) my_snprintf(char *s, size_t size, char const *format, ...)
{ {
int n; int n;

View File

@ -470,7 +470,7 @@ size_overflow(void)
memory_exhausted(_("size overflow")); memory_exhausted(_("size overflow"));
} }
ATTRIBUTE_REPRODUCIBLE static ptrdiff_t ATTRIBUTE_PURE_114833 static ptrdiff_t
size_sum(size_t a, size_t b) size_sum(size_t a, size_t b)
{ {
#ifdef ckd_add #ifdef ckd_add
@ -484,7 +484,7 @@ size_sum(size_t a, size_t b)
size_overflow(); size_overflow();
} }
ATTRIBUTE_REPRODUCIBLE static ptrdiff_t ATTRIBUTE_PURE_114833 static ptrdiff_t
size_product(ptrdiff_t nitems, ptrdiff_t itemsize) size_product(ptrdiff_t nitems, ptrdiff_t itemsize)
{ {
#ifdef ckd_mul #ifdef ckd_mul
@ -499,7 +499,7 @@ size_product(ptrdiff_t nitems, ptrdiff_t itemsize)
size_overflow(); size_overflow();
} }
ATTRIBUTE_REPRODUCIBLE static ptrdiff_t ATTRIBUTE_PURE_114833 static ptrdiff_t
align_to(ptrdiff_t size, ptrdiff_t alignment) align_to(ptrdiff_t size, ptrdiff_t alignment)
{ {
ptrdiff_t lo_bits = alignment - 1, sum = size_sum(size, lo_bits); ptrdiff_t lo_bits = alignment - 1, sum = size_sum(size, lo_bits);
@ -523,7 +523,7 @@ memcheck(void *ptr)
return ptr; return ptr;
} }
ATTRIBUTE_MALLOC static void * static void *
emalloc(size_t size) emalloc(size_t size)
{ {
return memcheck(malloc(size)); return memcheck(malloc(size));
@ -535,7 +535,7 @@ erealloc(void *ptr, size_t size)
return memcheck(realloc(ptr, size)); return memcheck(realloc(ptr, size));
} }
ATTRIBUTE_MALLOC static char * static char *
estrdup(char const *str) estrdup(char const *str)
{ {
return memcheck(strdup(str)); return memcheck(strdup(str));
@ -1435,7 +1435,7 @@ relname(char const *target, char const *linkname)
/* Return true if A and B must have the same parent dir if A and B exist. /* Return true if A and B must have the same parent dir if A and B exist.
Return false if this is not necessarily true (though it might be true). Return false if this is not necessarily true (though it might be true).
Keep it simple, and do not inspect the file system. */ Keep it simple, and do not inspect the file system. */
static bool ATTRIBUTE_PURE_114833 static bool
same_parent_dirs(char const *a, char const *b) same_parent_dirs(char const *a, char const *b)
{ {
for (; *a == *b; a++, b++) for (; *a == *b; a++, b++)
@ -2982,10 +2982,10 @@ rule_cmp(struct rule const *a, struct rule const *b)
return a->r_dayofmonth - b->r_dayofmonth; return a->r_dayofmonth - b->r_dayofmonth;
} }
/* Store into RESULT a POSIX.1-2017 TZ string that represent the future /* Store into RESULT a proleptic TZ string that represent the future
predictions for the zone ZPFIRST with ZONECOUNT entries. Return a predictions for the zone ZPFIRST with ZONECOUNT entries. Return a
compatibility indicator (a TZDB release year) if successful, a compatibility indicator (a TZDB release year) if successful, a
negative integer if no such TZ string exissts. */ negative integer if no such TZ string exists. */
static int static int
stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount) stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
{ {
@ -3177,8 +3177,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
if (noise) { if (noise) {
if (!*envvar) if (!*envvar)
warning("%s %s", warning("%s %s",
_("no POSIX.1-2017 environment variable" _("no proleptic TZ string for zone"),
" for zone"),
zpfirst->z_name); zpfirst->z_name);
else if (compat != 0) { else if (compat != 0) {
/* Circa-COMPAT clients, and earlier clients, might /* Circa-COMPAT clients, and earlier clients, might
@ -3442,7 +3441,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
if (do_extend) { if (do_extend) {
/* /*
** If we're extending the explicitly listed observations for ** If we're extending the explicitly listed observations for
** 400 years because we can't fill the POSIX.1-2017 TZ field, ** 400 years because we can't fill the proleptic TZ field,
** check whether we actually ended up explicitly listing ** check whether we actually ended up explicitly listing
** observations through that period. If there aren't any ** observations through that period. If there aren't any
** near the end of the 400-year period, add a redundant ** near the end of the 400-year period, add a redundant
@ -3627,7 +3626,7 @@ lowerit(char a)
} }
/* case-insensitive equality */ /* case-insensitive equality */
ATTRIBUTE_REPRODUCIBLE static bool ATTRIBUTE_PURE_114833 static bool
ciequal(register const char *ap, register const char *bp) ciequal(register const char *ap, register const char *bp)
{ {
while (lowerit(*ap) == lowerit(*bp++)) while (lowerit(*ap) == lowerit(*bp++))
@ -3636,7 +3635,7 @@ ciequal(register const char *ap, register const char *bp)
return false; return false;
} }
ATTRIBUTE_REPRODUCIBLE static bool ATTRIBUTE_PURE_114833 static bool
itsabbr(register const char *abbr, register const char *word) itsabbr(register const char *abbr, register const char *word)
{ {
if (lowerit(*abbr) != lowerit(*word)) if (lowerit(*abbr) != lowerit(*word))
@ -3652,7 +3651,7 @@ itsabbr(register const char *abbr, register const char *word)
/* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */ /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
ATTRIBUTE_REPRODUCIBLE static bool ATTRIBUTE_PURE_114833 static bool
ciprefix(char const *abbr, char const *word) ciprefix(char const *abbr, char const *word)
{ {
do do
@ -3762,7 +3761,7 @@ time_overflow(void)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ATTRIBUTE_REPRODUCIBLE static zic_t ATTRIBUTE_PURE_114833 static zic_t
oadd(zic_t t1, zic_t t2) oadd(zic_t t1, zic_t t2)
{ {
#ifdef ckd_add #ifdef ckd_add
@ -3776,7 +3775,7 @@ oadd(zic_t t1, zic_t t2)
time_overflow(); time_overflow();
} }
ATTRIBUTE_REPRODUCIBLE static zic_t ATTRIBUTE_PURE_114833 static zic_t
tadd(zic_t t1, zic_t t2) tadd(zic_t t1, zic_t t2)
{ {
#ifdef ckd_add #ifdef ckd_add