Update timezone code from tzcode 2018g.

This patch updates files coming from tzcode to the versions in tzcode
2018g.  No changes elsewhere in glibc were needed.

Tested for x86_64.

	* timezone/private.h: Update from tzcode 2018g.
	* timezone/tzfile.h: Likewise.
	* timezone/tzselect.ksh: Likewise.
	* timezone/zdump.c: Likewise.
	* timezone/zic.c: Likewise.
This commit is contained in:
Joseph Myers 2018-12-10 13:11:58 +00:00
parent b93f4052fc
commit 0afcb29d50
6 changed files with 609 additions and 339 deletions

View File

@ -1,3 +1,11 @@
2018-12-10 Joseph Myers <joseph@codesourcery.com>
* timezone/private.h: Update from tzcode 2018g.
* timezone/tzfile.h: Likewise.
* timezone/tzselect.ksh: Likewise.
* timezone/zdump.c: Likewise.
* timezone/zic.c: Likewise.
2018-12-08 Paul Pluzhnikov <ppluzhnikov@google.com> 2018-12-08 Paul Pluzhnikov <ppluzhnikov@google.com>
[BZ #23490] [BZ #23490]

View File

@ -1,3 +1,5 @@
/* Private header for tzdb code. */
#ifndef PRIVATE_H #ifndef PRIVATE_H
#define PRIVATE_H #define PRIVATE_H
@ -15,6 +17,16 @@
** Thank you! ** Thank you!
*/ */
/*
** zdump has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides.
** You can use zdump to help in verifying other implementations.
** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
*/
#ifndef USE_LTZ
# define USE_LTZ 1
#endif
/* This string was in the Factory zone through version 2016f. */ /* This string was in the Factory zone through version 2016f. */
#define GRANDPARENTED "Local time zone must be set--see zic manual page" #define GRANDPARENTED "Local time zone must be set--see zic manual page"
@ -27,13 +39,28 @@
#define HAVE_DECL_ASCTIME_R 1 #define HAVE_DECL_ASCTIME_R 1
#endif #endif
#if !defined HAVE_GENERIC && defined __has_extension
# if __has_extension(c_generic_selections)
# define HAVE_GENERIC 1
# else
# define HAVE_GENERIC 0
# endif
#endif
/* _Generic is buggy in pre-4.9 GCC. */
#if !defined HAVE_GENERIC && defined __GNUC__
# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
#endif
#ifndef HAVE_GENERIC
# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
#endif
#ifndef HAVE_GETTEXT #ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0 #define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */ #endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_INCOMPATIBLE_CTIME_R #ifndef HAVE_INCOMPATIBLE_CTIME_R
#define HAVE_INCOMPATIBLE_CTIME_R 0 #define HAVE_INCOMPATIBLE_CTIME_R 0
#endif /* !defined INCOMPATIBLE_CTIME_R */ #endif
#ifndef HAVE_LINK #ifndef HAVE_LINK
#define HAVE_LINK 1 #define HAVE_LINK 1
@ -43,10 +70,18 @@
#define HAVE_POSIX_DECLS 1 #define HAVE_POSIX_DECLS 1
#endif #endif
#ifndef HAVE_STDBOOL_H
#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
#endif
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
#define HAVE_STRDUP 1 #define HAVE_STRDUP 1
#endif #endif
#ifndef HAVE_STRTOLL
#define HAVE_STRTOLL 1
#endif
#ifndef HAVE_SYMLINK #ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1 #define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */ #endif /* !defined HAVE_SYMLINK */
@ -76,13 +111,23 @@
#define ctime_r _incompatible_ctime_r #define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */ #endif /* HAVE_INCOMPATIBLE_CTIME_R */
/* Enable tm_gmtoff and tm_zone on GNUish systems. */ /* Enable tm_gmtoff, tm_zone, and environ on GNUish systems. */
#define _GNU_SOURCE 1 #define _GNU_SOURCE 1
/* Fix asctime_r on Solaris 11. */ /* Fix asctime_r on Solaris 11. */
#define _POSIX_PTHREAD_SEMANTICS 1 #define _POSIX_PTHREAD_SEMANTICS 1
/* Enable strtoimax on pre-C99 Solaris 11. */ /* Enable strtoimax on pre-C99 Solaris 11. */
#define __EXTENSIONS__ 1 #define __EXTENSIONS__ 1
/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
enable large files on GNUish systems ... */
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
#endif
/* ... and on AIX ... */
#define _LARGE_FILES 1
/* ... and enable large inode numbers on Mac OS X 10.5 and later. */
#define _DARWIN_USE_64_BIT_INODE 1
/* /*
** Nested includes ** Nested includes
*/ */
@ -105,7 +150,6 @@
#undef tzfree #undef tzfree
#include <sys/types.h> /* for time_t */ #include <sys/types.h> /* for time_t */
#include <stdio.h>
#include <string.h> #include <string.h>
#include <limits.h> /* for CHAR_BIT et al. */ #include <limits.h> /* for CHAR_BIT et al. */
#include <stdlib.h> #include <stdlib.h>
@ -126,19 +170,8 @@
#include <libintl.h> #include <libintl.h>
#endif /* HAVE_GETTEXT */ #endif /* HAVE_GETTEXT */
#if HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
#endif /* HAVE_SYS_WAIT_H */
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0)
#endif /* !defined WIFEXITED */
#ifndef WEXITSTATUS
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#endif /* !defined WEXITSTATUS */
#if HAVE_UNISTD_H #if HAVE_UNISTD_H
#include <unistd.h> /* for F_OK, R_OK, and other POSIX goodness */ #include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */ #endif /* HAVE_UNISTD_H */
#ifndef HAVE_STRFTIME_L #ifndef HAVE_STRFTIME_L
@ -149,9 +182,22 @@
# endif # endif
#endif #endif
#ifndef F_OK #ifndef USG_COMPAT
#define F_OK 0 # ifndef _XOPEN_VERSION
#endif /* !defined F_OK */ # define USG_COMPAT 0
# else
# define USG_COMPAT 1
# endif
#endif
#ifndef HAVE_TZNAME
# if _POSIX_VERSION < 198808 && !USG_COMPAT
# define HAVE_TZNAME 0
# else
# define HAVE_TZNAME 1
# endif
#endif
#ifndef R_OK #ifndef R_OK
#define R_OK 4 #define R_OK 4
#endif /* !defined R_OK */ #endif /* !defined R_OK */
@ -236,15 +282,19 @@ typedef int int_fast32_t;
#ifndef INTMAX_MAX #ifndef INTMAX_MAX
# ifdef LLONG_MAX # ifdef LLONG_MAX
typedef long long intmax_t; typedef long long intmax_t;
# define strtoimax strtoll # if HAVE_STRTOLL
# define strtoimax strtoll
# endif
# define INTMAX_MAX LLONG_MAX # define INTMAX_MAX LLONG_MAX
# define INTMAX_MIN LLONG_MIN # define INTMAX_MIN LLONG_MIN
# else # else
typedef long intmax_t; typedef long intmax_t;
# define strtoimax strtol
# define INTMAX_MAX LONG_MAX # define INTMAX_MAX LONG_MAX
# define INTMAX_MIN LONG_MIN # define INTMAX_MIN LONG_MIN
# endif # endif
# ifndef strtoimax
# define strtoimax strtol
# endif
#endif #endif
#ifndef PRIdMAX #ifndef PRIdMAX
@ -294,12 +344,14 @@ typedef unsigned long uintmax_t;
#define SIZE_MAX ((size_t) -1) #define SIZE_MAX ((size_t) -1)
#endif #endif
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__) #if 3 <= __GNUC__
# define ATTRIBUTE_CONST __attribute__ ((const)) # define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# define ATTRIBUTE_PURE __attribute__ ((__pure__)) # define ATTRIBUTE_PURE __attribute__ ((__pure__))
# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) # define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else #else
# define ATTRIBUTE_CONST /* empty */ # define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_PURE /* empty */ # define ATTRIBUTE_PURE /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */ # define ATTRIBUTE_FORMAT(spec) /* empty */
#endif #endif
@ -326,6 +378,16 @@ typedef unsigned long uintmax_t;
#ifndef EPOCH_OFFSET #ifndef EPOCH_OFFSET
# define EPOCH_OFFSET 0 # define EPOCH_OFFSET 0
#endif #endif
#ifndef RESERVE_STD_EXT_IDS
# define RESERVE_STD_EXT_IDS 0
#endif
/* If standard C identifiers with external linkage (e.g., localtime)
are reserved and are not already being renamed anyway, rename them
as if compiling with '-Dtime_tz=time_t'. */
#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
# define time_tz time_t
#endif
/* /*
** Compile with -Dtime_tz=T to build the tz package with a private ** Compile with -Dtime_tz=T to build the tz package with a private
@ -335,6 +397,12 @@ typedef unsigned long uintmax_t;
** typical platforms. ** typical platforms.
*/ */
#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0 #if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
# define TZ_TIME_T 1
#else
# define TZ_TIME_T 0
#endif
#if TZ_TIME_T
# ifdef LOCALTIME_IMPLEMENTATION # ifdef LOCALTIME_IMPLEMENTATION
static time_t sys_time(time_t *x) { return time(x); } static time_t sys_time(time_t *x) { return time(x); }
# endif # endif
@ -367,6 +435,8 @@ typedef time_tz tz_time_t;
# define posix2time tz_posix2time # define posix2time tz_posix2time
# undef posix2time_z # undef posix2time_z
# define posix2time_z tz_posix2time_z # define posix2time_z tz_posix2time_z
# undef strftime
# define strftime tz_strftime
# undef time # undef time
# define time tz_time # define time tz_time
# undef time2posix # undef time2posix
@ -389,10 +459,34 @@ typedef time_tz tz_time_t;
# define tzset tz_tzset # define tzset tz_tzset
# undef tzsetwall # undef tzsetwall
# define tzsetwall tz_tzsetwall # define tzsetwall tz_tzsetwall
# if HAVE_STRFTIME_L
# undef strftime_l
# define strftime_l tz_strftime_l
# endif
# if HAVE_TZNAME
# undef tzname
# define tzname tz_tzname
# endif
# if USG_COMPAT
# undef daylight
# define daylight tz_daylight
# undef timezone
# define timezone tz_timezone
# endif
# ifdef ALTZONE
# undef altzone
# define altzone tz_altzone
# endif
char *ctime(time_t const *); char *ctime(time_t const *);
char *ctime_r(time_t const *, char *); char *ctime_r(time_t const *, char *);
double difftime(time_t, time_t); double difftime(time_t, time_t) ATTRIBUTE_CONST;
size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict);
# if HAVE_STRFTIME_L
size_t strftime_l(char *restrict, size_t, char const *restrict,
struct tm const *restrict, locale_t);
# endif
struct tm *gmtime(time_t const *); struct tm *gmtime(time_t const *);
struct tm *gmtime_r(time_t const *restrict, struct tm *restrict); struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
struct tm *localtime(time_t const *); struct tm *localtime(time_t const *);
@ -406,18 +500,29 @@ void tzset(void);
extern char *asctime_r(struct tm const *restrict, char *restrict); extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif #endif
#if !HAVE_POSIX_DECLS #ifndef HAVE_DECL_ENVIRON
# ifdef USG_COMPAT # if defined environ || defined __USE_GNU
# ifndef timezone # define HAVE_DECL_ENVIRON 1
extern long timezone; # else
# endif # define HAVE_DECL_ENVIRON 0
# ifndef daylight
extern int daylight;
# endif
# endif # endif
#endif #endif
#if defined ALTZONE && !defined altzone #if !HAVE_DECL_ENVIRON
extern char **environ;
#endif
#if TZ_TIME_T || !HAVE_POSIX_DECLS
# if HAVE_TZNAME
extern char *tzname[];
# endif
# if USG_COMPAT
extern long timezone;
extern int daylight;
# endif
#endif
#ifdef ALTZONE
extern long altzone; extern long altzone;
#endif #endif
@ -427,25 +532,25 @@ extern long altzone;
*/ */
#ifdef STD_INSPIRED #ifdef STD_INSPIRED
# if !defined tzsetwall || defined time_tz # if TZ_TIME_T || !defined tzsetwall
void tzsetwall(void); void tzsetwall(void);
# endif # endif
# if !defined offtime || defined time_tz # if TZ_TIME_T || !defined offtime
struct tm *offtime(time_t const *, long); struct tm *offtime(time_t const *, long);
# endif # endif
# if !defined timegm || defined time_tz # if TZ_TIME_T || !defined timegm
time_t timegm(struct tm *); time_t timegm(struct tm *);
# endif # endif
# if !defined timelocal || defined time_tz # if TZ_TIME_T || !defined timelocal
time_t timelocal(struct tm *); time_t timelocal(struct tm *);
# endif # endif
# if !defined timeoff || defined time_tz # if TZ_TIME_T || !defined timeoff
time_t timeoff(struct tm *, long); time_t timeoff(struct tm *, long);
# endif # endif
# if !defined time2posix || defined time_tz # if TZ_TIME_T || !defined time2posix
time_t time2posix(time_t); time_t time2posix(time_t);
# endif # endif
# if !defined posix2time || defined time_tz # if TZ_TIME_T || !defined posix2time
time_t posix2time(time_t); time_t posix2time(time_t);
# endif # endif
#endif #endif
@ -479,10 +584,10 @@ time_t mktime_z(timezone_t restrict, struct tm *restrict);
timezone_t tzalloc(char const *); timezone_t tzalloc(char const *);
void tzfree(timezone_t); void tzfree(timezone_t);
# ifdef STD_INSPIRED # ifdef STD_INSPIRED
# if !defined posix2time_z || defined time_tz # if TZ_TIME_T || !defined posix2time_z
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE; time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif # endif
# if !defined time2posix_z || defined time_tz # if TZ_TIME_T || !defined time2posix_z
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE; time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
# endif # endif
# endif # endif
@ -492,12 +597,12 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
** Finally, some convenience items. ** Finally, some convenience items.
*/ */
#if __STDC_VERSION__ < 199901 #if HAVE_STDBOOL_H
# include <stdbool.h>
#else
# define true 1 # define true 1
# define false 0 # define false 0
# define bool int # define bool int
#else
# include <stdbool.h>
#endif #endif
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
@ -513,27 +618,32 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
#define MINVAL(t, b) \ #define MINVAL(t, b) \
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0)) ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
/* The minimum and maximum finite time values. This implementation /* The extreme time values, assuming no padding. */
assumes no padding if time_t is signed and either the compiler is #define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
pre-C11 or time_t is not one of the standard signed integer types. */ #define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
#if 201112 <= __STDC_VERSION__
static time_t const time_t_min /* The extreme time values. These are macros, not constants, so that
= (TYPE_SIGNED(time_t) any portability problem occur only when compiling .c files that use
? _Generic((time_t) 0, the macros, which is safer for applications that need only zdump and zic.
signed char: SCHAR_MIN, short: SHRT_MIN, This implementation assumes no padding if time_t is signed and
int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, either the compiler lacks support for _Generic or time_t is not one
default: MINVAL(time_t, TYPE_BIT(time_t))) of the standard signed integer types. */
: 0); #if HAVE_GENERIC
static time_t const time_t_max # define TIME_T_MIN \
= (TYPE_SIGNED(time_t) _Generic((time_t) 0, \
? _Generic((time_t) 0, signed char: SCHAR_MIN, short: SHRT_MIN, \
signed char: SCHAR_MAX, short: SHRT_MAX, int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, default: TIME_T_MIN_NO_PADDING)
default: MAXVAL(time_t, TYPE_BIT(time_t))) # define TIME_T_MAX \
: -1); (TYPE_SIGNED(time_t) \
? _Generic((time_t) 0, \
signed char: SCHAR_MAX, short: SHRT_MAX, \
int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
default: TIME_T_MAX_NO_PADDING) \
: (time_t) -1)
#else #else
static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t)); # define TIME_T_MIN TIME_T_MIN_NO_PADDING
static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t)); # define TIME_T_MAX TIME_T_MAX_NO_PADDING
#endif #endif
/* /*
@ -550,7 +660,7 @@ static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
** INITIALIZE(x) ** INITIALIZE(x)
*/ */
#ifdef lint #ifdef GCC_LINT
# define INITIALIZE(x) ((x) = 0) # define INITIALIZE(x) ((x) = 0)
#else #else
# define INITIALIZE(x) # define INITIALIZE(x)
@ -633,7 +743,7 @@ char *ctime_r(time_t const *, char *);
** or ** or
** isleap(a + b) == isleap(a % 400 + b % 400) ** isleap(a + b) == isleap(a % 400 + b % 400)
** This is true even if % means modulo rather than Fortran remainder ** This is true even if % means modulo rather than Fortran remainder
** (which is allowed by C89 but not C99). ** (which is allowed by C89 but not by C99 or later).
** We use this to avoid addition overflow problems. ** We use this to avoid addition overflow problems.
*/ */

View File

@ -1,3 +1,5 @@
/* Layout and location of TZif files. */
#ifndef TZFILE_H #ifndef TZFILE_H
#define TZFILE_H #define TZFILE_H
@ -20,11 +22,11 @@
*/ */
#ifndef TZDIR #ifndef TZDIR
#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */ #define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */ #endif /* !defined TZDIR */
#ifndef TZDEFAULT #ifndef TZDEFAULT
#define TZDEFAULT "localtime" #define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */ #endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES #ifndef TZDEFRULES

View File

@ -1,12 +1,11 @@
#!/bin/bash #!/bin/bash
# Ask the user about the time zone, and output the resulting TZ value to stdout.
# Interact with the user via stderr and stdin.
PKGVERSION='(tzcode) ' PKGVERSION='(tzcode) '
TZVERSION=see_Makefile TZVERSION=see_Makefile
REPORT_BUGS_TO=tz@iana.org REPORT_BUGS_TO=tz@iana.org
# Ask the user about the time zone, and output the resulting TZ value to stdout.
# Interact with the user via stderr and stdin.
# Contributed by Paul Eggert. This file is in the public domain. # Contributed by Paul Eggert. This file is in the public domain.
# Porting notes: # Porting notes:
@ -17,9 +16,9 @@ REPORT_BUGS_TO=tz@iana.org
# If your host lacks both Bash and the Korn shell, you can get their # If your host lacks both Bash and the Korn shell, you can get their
# source from one of these locations: # source from one of these locations:
# #
# Bash <http://www.gnu.org/software/bash/bash.html> # Bash <https://www.gnu.org/software/bash/>
# Korn Shell <http://www.kornshell.com/> # Korn Shell <http://www.kornshell.com/>
# Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/> # MirBSD Korn Shell <https://www.mirbsd.org/mksh.htm>
# #
# For portability to Solaris 9 /bin/sh this script avoids some POSIX # For portability to Solaris 9 /bin/sh this script avoids some POSIX
# features and common extensions, such as $(...) (which works sometimes # features and common extensions, such as $(...) (which works sometimes
@ -29,8 +28,8 @@ REPORT_BUGS_TO=tz@iana.org
# 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 either of the following free programs instead: # you can use either of the following free programs instead:
# #
# Gawk (GNU awk) <http://www.gnu.org/software/gawk/> # Gawk (GNU awk) <https://www.gnu.org/software/gawk/>
# mawk <http://invisible-island.net/mawk/> # mawk <https://invisible-island.net/mawk/>
# Specify default values for environment variables if they are unset. # Specify default values for environment variables if they are unset.
@ -55,7 +54,7 @@ location_limit=10
zonetabtype=zone1970 zonetabtype=zone1970
usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT] usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
Select a time zone interactively. Select a timezone interactively.
Options: Options:
@ -327,7 +326,7 @@ while
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 time zone using the Posix TZ format." "TZ - I want to specify the timezone using the Posix TZ format."
continent=$select_result continent=$select_result
case $continent in case $continent in
Americas) continent=America;; Americas) continent=America;;
@ -342,8 +341,10 @@ while
while while
echo >&2 'Please enter the desired value' \ echo >&2 'Please enter the desired value' \
'of the TZ environment variable.' 'of the TZ environment variable.'
echo >&2 'For example, GST-10 is a zone named GST' \ echo >&2 'For example, AEST-10 is abbreviated' \
'that is 10 hours ahead (east) of UTC.' 'AEST and is 10 hours'
echo >&2 'ahead (east) of Greenwich,' \
'with no daylight saving time.'
read TZ read TZ
$AWK -v TZ="$TZ" 'BEGIN { $AWK -v TZ="$TZ" 'BEGIN {
tzname = "(<[[:alnum:]+-]{3,}>|[[:alpha:]]{3,})" tzname = "(<[[:alnum:]+-]{3,}>|[[:alpha:]]{3,})"
@ -360,7 +361,7 @@ while
exit 0 exit 0
}' }'
do do
say >&2 "'$TZ' is not a conforming Posix time zone string." say >&2 "'$TZ' is not a conforming Posix timezone string."
done done
TZ_for_date=$TZ;; TZ_for_date=$TZ;;
*) *)
@ -386,8 +387,7 @@ while
BEGIN { FS = "\t" } BEGIN { FS = "\t" }
{ print $NF } { print $NF }
'` '`
echo >&2 'Please select one of the following' \ echo >&2 'Please select one of the following timezones,' \
'time zone regions,'
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
@ -437,7 +437,7 @@ while
esac esac
# Get list of names of time zone rule regions in the country. # Get list of timezones in the country.
regions=`$AWK \ regions=`$AWK \
-v country="$country" \ -v country="$country" \
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
@ -460,8 +460,7 @@ while
# 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
*"$newline"*) *"$newline"*)
echo >&2 'Please select one of the following' \ echo >&2 'Please select one of the following timezones.'
'time zone regions.'
doselect $regions doselect $regions
region=$select_result;; region=$select_result;;
*) *)

View File

@ -1,3 +1,5 @@
/* Dump time zone data in a textual format. */
/* /*
** This file is in the public domain, so clarified as of ** This file is in the public domain, so clarified as of
** 2009-05-17 by Arthur David Olson. ** 2009-05-17 by Arthur David Olson.
@ -5,21 +7,16 @@
#include "version.h" #include "version.h"
/*
** This code has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides.
** You can use this code to help in verifying other implementations.
** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
*/
#ifndef NETBSD_INSPIRED #ifndef NETBSD_INSPIRED
# define NETBSD_INSPIRED 1 # define NETBSD_INSPIRED 1
#endif #endif
#ifndef USE_LTZ
# define USE_LTZ 1
#endif
#include "private.h" #include "private.h"
#include <stdio.h>
#ifndef HAVE_SNPRINTF
# define HAVE_SNPRINTF (199901 <= __STDC_VERSION__)
#endif
#ifndef HAVE_LOCALTIME_R #ifndef HAVE_LOCALTIME_R
# define HAVE_LOCALTIME_R 1 # define HAVE_LOCALTIME_R 1
@ -72,14 +69,11 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
# define timezone_t char ** # define timezone_t char **
#endif #endif
extern char ** environ;
#if !HAVE_POSIX_DECLS #if !HAVE_POSIX_DECLS
extern int getopt(int argc, char * const argv[], extern int getopt(int argc, char * const argv[],
const char * options); const char * options);
extern char * optarg; extern char * optarg;
extern int optind; extern int optind;
extern char * tzname[];
#endif #endif
/* The minimum and maximum finite time values. */ /* The minimum and maximum finite time values. */
@ -144,7 +138,7 @@ sumsize(size_t a, size_t b)
/* 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 nonzero. */ on failure. SIZE should be nonzero. */
static void * static void * ATTRIBUTE_MALLOC
xmalloc(size_t size) xmalloc(size_t size)
{ {
void *p = malloc(size); void *p = malloc(size);
@ -263,7 +257,7 @@ tzfree(timezone_t env)
} }
#endif /* ! USE_LOCALTIME_RZ */ #endif /* ! USE_LOCALTIME_RZ */
/* A UTC time zone, and its initializer. */ /* A UT time zone, and its initializer. */
static timezone_t gmtz; static timezone_t gmtz;
static void static void
gmtzinit(void) gmtzinit(void)
@ -278,7 +272,7 @@ gmtzinit(void)
} }
} }
/* Convert *TP to UTC, storing the broken-down time into *TMP. /* Convert *TP to UT, storing the broken-down time into *TMP.
Return TMP if successful, NULL otherwise. This is like gmtime_r(TP, TMP), Return TMP if successful, NULL otherwise. This is like gmtime_r(TP, TMP),
except typically faster if USE_LOCALTIME_RZ. */ except typically faster if USE_LOCALTIME_RZ. */
static struct tm * static struct tm *
@ -390,7 +384,7 @@ static void
usage(FILE * const stream, const int status) usage(FILE * const stream, const int status)
{ {
fprintf(stream, fprintf(stream,
_("%s: usage: %s OPTIONS ZONENAME ...\n" _("%s: usage: %s OPTIONS TIMEZONE ...\n"
"Options include:\n" "Options include:\n"
" -c [L,]U Start at year L (default -500), end before year U (default 2500)\n" " -c [L,]U Start at year L (default -500), end before year U (default 2500)\n"
" -t [L,]U Start at time L, end before time U (in seconds since 1970)\n" " -t [L,]U Start at time L, end before time U (in seconds since 1970)\n"
@ -550,6 +544,7 @@ main(int argc, char *argv[])
} }
if (t < cutlotime) if (t < cutlotime)
t = cutlotime; t = cutlotime;
INITIALIZE (ab);
tm_ok = my_localtime_rz(tz, &t, &tm) != NULL; tm_ok = my_localtime_rz(tz, &t, &tm) != NULL;
if (tm_ok) { if (tm_ok) {
ab = saveabbr(&abbrev, &abbrevsize, &tm); ab = saveabbr(&abbrev, &abbrevsize, &tm);
@ -565,11 +560,10 @@ main(int argc, char *argv[])
: cuthitime); : cuthitime);
struct tm *newtmp = localtime_rz(tz, &newt, &newtm); struct tm *newtmp = localtime_rz(tz, &newt, &newtm);
bool newtm_ok = newtmp != NULL; bool newtm_ok = newtmp != NULL;
if (! (tm_ok & newtm_ok if (tm_ok != newtm_ok
? (delta(&newtm, &tm) == newt - t || (tm_ok && (delta(&newtm, &tm) != newt - t
&& newtm.tm_isdst == tm.tm_isdst || newtm.tm_isdst != tm.tm_isdst
&& strcmp(abbr(&newtm), ab) == 0) || strcmp(abbr(&newtm), ab) != 0))) {
: tm_ok == newtm_ok)) {
newt = hunt(tz, argv[i], t, newt); newt = hunt(tz, argv[i], t, newt);
newtmp = localtime_rz(tz, &newt, &newtm); newtmp = localtime_rz(tz, &newt, &newtm);
newtm_ok = newtmp != NULL; newtm_ok = newtmp != NULL;
@ -685,17 +679,15 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit)
} }
/* /*
** Thanks to Paul Eggert for logic used in delta. ** Thanks to Paul Eggert for logic used in delta_nonneg.
*/ */
static intmax_t static intmax_t
delta(struct tm * newp, struct tm *oldp) delta_nonneg(struct tm *newp, struct tm *oldp)
{ {
register intmax_t result; register intmax_t result;
register int tmy; register int tmy;
if (newp->tm_year < oldp->tm_year)
return -delta(oldp, newp);
result = 0; result = 0;
for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE); result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
@ -709,6 +701,14 @@ delta(struct tm * newp, struct tm *oldp)
return result; return result;
} }
static intmax_t
delta(struct tm *newp, struct tm *oldp)
{
return (newp->tm_year < oldp->tm_year
? -delta_nonneg(oldp, newp)
: delta_nonneg(newp, oldp));
}
#ifndef TM_GMTOFF #ifndef TM_GMTOFF
/* Return A->tm_yday, adjusted to compare it fairly to B->tm_yday. /* Return A->tm_yday, adjusted to compare it fairly to B->tm_yday.
Assume A and B differ by at most one year. */ Assume A and B differ by at most one year. */
@ -722,8 +722,8 @@ adjusted_yday(struct tm const *a, struct tm const *b)
} }
#endif #endif
/* If A is the broken-down local time and B the broken-down UTC for /* If A is the broken-down local time and B the broken-down UT for
the same instant, return A's UTC offset in seconds, where positive the same instant, return A's UT offset in seconds, where positive
offsets are east of Greenwich. On failure, return LONG_MIN. offsets are east of Greenwich. On failure, return LONG_MIN.
If T is nonnull, *T is the timestamp that corresponds to A; call If T is nonnull, *T is the timestamp that corresponds to A; call
@ -787,6 +787,40 @@ show(timezone_t tz, char *zone, time_t t, bool v)
abbrok(abbr(tmp), zone); abbrok(abbr(tmp), zone);
} }
#if HAVE_SNPRINTF
# define my_snprintf snprintf
#else
# include <stdarg.h>
/* A substitute for snprintf that is good enough for zdump. */
static int ATTRIBUTE_FORMAT((printf, 3, 4))
my_snprintf(char *s, size_t size, char const *format, ...)
{
int n;
va_list args;
char const *arg;
size_t arglen, slen;
char buf[1024];
va_start(args, format);
if (strcmp(format, "%s") == 0) {
arg = va_arg(args, char const *);
arglen = strlen(arg);
} else {
n = vsprintf(buf, format, args);
if (n < 0)
return n;
arg = buf;
arglen = n;
}
slen = arglen < size ? arglen : size - 1;
memcpy(s, arg, slen);
s[slen] = '\0';
n = arglen <= INT_MAX ? arglen : -1;
va_end(args);
return n;
}
#endif
/* Store into BUF, of size SIZE, a formatted local time taken from *TM. /* Store into BUF, of size SIZE, a formatted local time taken from *TM.
Use ISO 8601 format +HH:MM:SS. Omit :SS if SS is zero, and omit Use ISO 8601 format +HH:MM:SS. Omit :SS if SS is zero, and omit
:MM too if MM is also zero. :MM too if MM is also zero.
@ -799,16 +833,16 @@ format_local_time(char *buf, size_t size, struct tm const *tm)
{ {
int ss = tm->tm_sec, mm = tm->tm_min, hh = tm->tm_hour; int ss = tm->tm_sec, mm = tm->tm_min, hh = tm->tm_hour;
return (ss return (ss
? snprintf(buf, size, "%02d:%02d:%02d", hh, mm, ss) ? my_snprintf(buf, size, "%02d:%02d:%02d", hh, mm, ss)
: mm : mm
? snprintf(buf, size, "%02d:%02d", hh, mm) ? my_snprintf(buf, size, "%02d:%02d", hh, mm)
: snprintf(buf, size, "%02d", hh)); : my_snprintf(buf, size, "%02d", hh));
} }
/* Store into BUF, of size SIZE, a formatted UTC offset for the /* Store into BUF, of size SIZE, a formatted UT offset for the
localtime *TM corresponding to time T. Use ISO 8601 format localtime *TM corresponding to time T. Use ISO 8601 format
+HHMMSS, or -HHMMSS for timestamps west of Greenwich; use the +HHMMSS, or -HHMMSS for timestamps west of Greenwich; use the
format -00 for unknown UTC offsets. If the hour needs more than format -00 for unknown UT offsets. If the hour needs more than
two digits to represent, extend the length of HH as needed. two digits to represent, extend the length of HH as needed.
Otherwise, omit SS if SS is zero, and omit MM too if MM is also Otherwise, omit SS if SS is zero, and omit MM too if MM is also
zero. zero.
@ -837,10 +871,10 @@ format_utc_offset(char *buf, size_t size, struct tm const *tm, time_t t)
mm = off / 60 % 60; mm = off / 60 % 60;
hh = off / 60 / 60; hh = off / 60 / 60;
return (ss || 100 <= hh return (ss || 100 <= hh
? snprintf(buf, size, "%c%02ld%02d%02d", sign, hh, mm, ss) ? my_snprintf(buf, size, "%c%02ld%02d%02d", sign, hh, mm, ss)
: mm : mm
? snprintf(buf, size, "%c%02ld%02d", sign, hh, mm) ? my_snprintf(buf, size, "%c%02ld%02d", sign, hh, mm)
: snprintf(buf, size, "%c%02ld", sign, hh)); : my_snprintf(buf, size, "%c%02ld", sign, hh));
} }
/* Store into BUF (of size SIZE) a quoted string representation of P. /* Store into BUF (of size SIZE) a quoted string representation of P.
@ -883,7 +917,7 @@ format_quoted_string(char *buf, size_t size, char const *p)
%f zone name %f zone name
%L local time as per format_local_time %L local time as per format_local_time
%Q like "U\t%Z\tD" where U is the UTC offset as for format_utc_offset %Q like "U\t%Z\tD" where U is the UT offset as for format_utc_offset
and D is the isdst flag; except omit D if it is zero, omit %Z if and D is the isdst flag; except omit D if it is zero, omit %Z if
it equals U, quote and escape %Z if it contains nonalphabetics, it equals U, quote and escape %Z if it contains nonalphabetics,
and omit any trailing tabs. */ and omit any trailing tabs. */
@ -943,15 +977,16 @@ istrftime(char *buf, size_t size, char const *time_fmt,
for (abp = ab; is_alpha(*abp); abp++) for (abp = ab; is_alpha(*abp); abp++)
continue; continue;
len = (!*abp && *ab len = (!*abp && *ab
? snprintf(b, s, "%s", ab) ? my_snprintf(b, s, "%s", ab)
: format_quoted_string(b, s, ab)); : format_quoted_string(b, s, ab));
if (s <= len) if (s <= len)
return false; return false;
b += len, s -= len; b += len, s -= len;
} }
formatted_len = (tm->tm_isdst formatted_len
? snprintf(b, s, &"\t\t%d"[show_abbr], tm->tm_isdst) = (tm->tm_isdst
: 0); ? my_snprintf(b, s, &"\t\t%d"[show_abbr], tm->tm_isdst)
: 0);
} }
break; break;
} }
@ -993,9 +1028,11 @@ abbr(struct tm const *tmp)
#ifdef TM_ZONE #ifdef TM_ZONE
return tmp->TM_ZONE; return tmp->TM_ZONE;
#else #else
return (0 <= tmp->tm_isdst && tzname[0 < tmp->tm_isdst] # if HAVE_TZNAME
? tzname[0 < tmp->tm_isdst] if (0 <= tmp->tm_isdst && tzname[0 < tmp->tm_isdst])
: ""); return tzname[0 < tmp->tm_isdst];
# endif
return "";
#endif #endif
} }
@ -1030,10 +1067,10 @@ tformat(void)
static void static void
dumptime(register const struct tm *timeptr) dumptime(register const struct tm *timeptr)
{ {
static const char wday_name[][3] = { static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
}; };
static const char mon_name[][3] = { static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
}; };
@ -1059,7 +1096,7 @@ dumptime(register const struct tm *timeptr)
(int) (sizeof mon_name / sizeof mon_name[0])) (int) (sizeof mon_name / sizeof mon_name[0]))
mn = "???"; mn = "???";
else mn = mon_name[timeptr->tm_mon]; else mn = mon_name[timeptr->tm_mon];
printf("%.3s %.3s%3d %.2d:%.2d:%.2d ", printf("%s %s%3d %.2d:%.2d:%.2d ",
wn, mn, wn, mn,
timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec); timeptr->tm_min, timeptr->tm_sec);

File diff suppressed because it is too large Load Diff