Merge "Bump tzcode from 2016g to 2022a*." am: 0219fe82c6
Original change: https://android-review.googlesource.com/c/platform/bionic/+/1985266 Change-Id: I46d908bd069f53544dfb89ed22a5eb37a294a166 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
7902bfcf9d
9 changed files with 1063 additions and 593 deletions
|
@ -259,18 +259,20 @@ cc_library_static {
|
|||
// Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
|
||||
"-DSTD_INSPIRED",
|
||||
// Obviously, we want to be thread-safe.
|
||||
"-DTHREAD_SAFE",
|
||||
"-DTHREAD_SAFE=1",
|
||||
// The name of the tm_gmtoff field in our struct tm.
|
||||
"-DTM_GMTOFF=tm_gmtoff",
|
||||
// Where we store our tzdata.
|
||||
"-DTZDIR=\"/system/usr/share/zoneinfo\"",
|
||||
// Include `tzname`, `timezone`, and `daylight` globals.
|
||||
"-DHAVE_POSIX_DECLS=0",
|
||||
"-DUSG_COMPAT=1",
|
||||
"-DUSG_COMPAT=2",
|
||||
"-DHAVE_TZNAME=2",
|
||||
// stdbool.h is available
|
||||
"-DHAVE_STDBOOL_H",
|
||||
// Use the empty string (instead of " ") as the timezone abbreviation
|
||||
// fallback.
|
||||
"-DWILDABBR=\"\"",
|
||||
"-DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU",
|
||||
"-Dlint",
|
||||
],
|
||||
|
||||
|
|
|
@ -483,6 +483,11 @@ static Time64_T seconds_between_years(Year left_year, Year right_year) {
|
|||
}
|
||||
|
||||
|
||||
/* This implementation violates mktime specification, according to which
|
||||
tm_yday, tm_wday, and tm_isdst fields should be updated. This function
|
||||
leaves input_date unmodified. Given that there were no bug reports, fixing
|
||||
it might cause more troubles than just leaving it as it is.
|
||||
*/
|
||||
Time64_T mktime64(const struct TM *input_date) {
|
||||
struct tm safe_date;
|
||||
struct TM date;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000. */
|
||||
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** 1996-06-05 by Arthur David Olson.
|
||||
|
@ -12,7 +14,7 @@
|
|||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
#include "tzfile.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
** Some systems only handle "%.2d"; others only handle "%02d";
|
||||
|
@ -29,13 +31,13 @@
|
|||
** leading zeroes to get the newline in the traditional place.
|
||||
** The -4 ensures that we get four characters of output even if
|
||||
** we call a strftime variant that produces fewer characters for some years.
|
||||
** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
|
||||
** The ISO C and POSIX standards prohibit padding the year,
|
||||
** but many implementations pad anyway; most likely the standards are buggy.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
|
||||
#define ASCTIME_FMT "%s %s%3d %2.2d:%2.2d:%2.2d %-4s\n"
|
||||
#else /* !defined __GNUC__ */
|
||||
#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
|
||||
#define ASCTIME_FMT "%s %s%3d %02.2d:%02.2d:%02.2d %-4s\n"
|
||||
#endif /* !defined __GNUC__ */
|
||||
/*
|
||||
** For years that are more than four digits we put extra spaces before the year
|
||||
|
@ -44,9 +46,9 @@
|
|||
** that no output is better than wrong output).
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
|
||||
#define ASCTIME_FMT_B "%s %s%3d %2.2d:%2.2d:%2.2d %s\n"
|
||||
#else /* !defined __GNUC__ */
|
||||
#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
|
||||
#define ASCTIME_FMT_B "%s %s%3d %02.2d:%02.2d:%02.2d %s\n"
|
||||
#endif /* !defined __GNUC__ */
|
||||
|
||||
#define STD_ASCTIME_BUF_SIZE 26
|
||||
|
@ -64,17 +66,13 @@
|
|||
|
||||
static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
|
||||
|
||||
/*
|
||||
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
|
||||
*/
|
||||
|
||||
char *
|
||||
asctime_r(register const struct tm *timeptr, char *buf)
|
||||
{
|
||||
static const char wday_name[][3] = {
|
||||
static const char wday_name[][4] = {
|
||||
"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",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
@ -117,10 +115,6 @@ asctime_r(register const struct tm *timeptr, char *buf)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
|
||||
*/
|
||||
|
||||
char *
|
||||
asctime(register const struct tm *timeptr)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* Return the difference between two timestamps. */
|
||||
|
||||
/*
|
||||
** This file is in the public domain, so clarified as of
|
||||
** 1996-06-05 by Arthur David Olson.
|
||||
|
@ -14,14 +16,14 @@ dminus(double x)
|
|||
return -x;
|
||||
}
|
||||
|
||||
double ATTRIBUTE_CONST
|
||||
double
|
||||
difftime(time_t time1, time_t time0)
|
||||
{
|
||||
/*
|
||||
** If double is large enough, simply convert and subtract
|
||||
** (assuming that the larger type has more precision).
|
||||
*/
|
||||
if (sizeof (time_t) < sizeof (double)) {
|
||||
if (sizeof(time_t) < sizeof(double)) {
|
||||
double t1 = time1, t0 = time0;
|
||||
return t1 - t0;
|
||||
}
|
||||
|
@ -34,7 +36,7 @@ difftime(time_t time1, time_t time0)
|
|||
return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
|
||||
|
||||
/* Use uintmax_t if wide enough. */
|
||||
if (sizeof (time_t) <= sizeof (uintmax_t)) {
|
||||
if (sizeof(time_t) <= sizeof(uintmax_t)) {
|
||||
uintmax_t t1 = time1, t0 = time0;
|
||||
return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,5 @@
|
|||
/* Private header for tzdb code. */
|
||||
|
||||
#ifndef PRIVATE_H
|
||||
|
||||
#define PRIVATE_H
|
||||
|
@ -15,6 +17,17 @@
|
|||
** 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. */
|
||||
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
|
||||
|
||||
/*
|
||||
|
@ -26,26 +39,53 @@
|
|||
#define HAVE_DECL_ASCTIME_R 1
|
||||
#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
|
||||
#define HAVE_GETTEXT 0
|
||||
#endif /* !defined HAVE_GETTEXT */
|
||||
|
||||
#ifndef HAVE_INCOMPATIBLE_CTIME_R
|
||||
#define HAVE_INCOMPATIBLE_CTIME_R 0
|
||||
#endif /* !defined INCOMPATIBLE_CTIME_R */
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LINK
|
||||
#define HAVE_LINK 1
|
||||
#endif /* !defined HAVE_LINK */
|
||||
|
||||
#ifndef HAVE_MALLOC_ERRNO
|
||||
#define HAVE_MALLOC_ERRNO 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_POSIX_DECLS
|
||||
#define HAVE_POSIX_DECLS 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STDBOOL_H
|
||||
#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
#define HAVE_STRDUP 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRTOLL
|
||||
#define HAVE_STRTOLL 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYMLINK
|
||||
#define HAVE_SYMLINK 1
|
||||
#endif /* !defined HAVE_SYMLINK */
|
||||
|
@ -54,10 +94,6 @@
|
|||
#define HAVE_SYS_STAT_H 1
|
||||
#endif /* !defined HAVE_SYS_STAT_H */
|
||||
|
||||
#ifndef HAVE_SYS_WAIT_H
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
#endif /* !defined HAVE_SYS_WAIT_H */
|
||||
|
||||
#ifndef HAVE_UNISTD_H
|
||||
#define HAVE_UNISTD_H 1
|
||||
#endif /* !defined HAVE_UNISTD_H */
|
||||
|
@ -75,22 +111,37 @@
|
|||
#define ctime_r _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
|
||||
/* Fix asctime_r on Solaris 10. */
|
||||
/* Fix asctime_r on Solaris 11. */
|
||||
#define _POSIX_PTHREAD_SEMANTICS 1
|
||||
/* Enable strtoimax on Solaris 10. */
|
||||
/* Enable strtoimax on pre-C99 Solaris 11. */
|
||||
#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
|
||||
*/
|
||||
|
||||
/* Avoid clashes with NetBSD by renaming NetBSD's declarations. */
|
||||
/* Avoid clashes with NetBSD by renaming NetBSD's declarations.
|
||||
If defining the 'timezone' variable, avoid a clash with FreeBSD's
|
||||
'timezone' function by renaming its declaration. */
|
||||
#define localtime_rz sys_localtime_rz
|
||||
#define mktime_z sys_mktime_z
|
||||
#define posix2time_z sys_posix2time_z
|
||||
#define time2posix_z sys_time2posix_z
|
||||
#if defined USG_COMPAT && USG_COMPAT == 2
|
||||
# define timezone sys_timezone
|
||||
#endif
|
||||
#define timezone_t sys_timezone_t
|
||||
#define tzalloc sys_tzalloc
|
||||
#define tzfree sys_tzfree
|
||||
|
@ -99,21 +150,30 @@
|
|||
#undef mktime_z
|
||||
#undef posix2time_z
|
||||
#undef time2posix_z
|
||||
#if defined USG_COMPAT && USG_COMPAT == 2
|
||||
# undef timezone
|
||||
#endif
|
||||
#undef timezone_t
|
||||
#undef tzalloc
|
||||
#undef tzfree
|
||||
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "limits.h" /* for CHAR_BIT et al. */
|
||||
#include "stdlib.h"
|
||||
#include <sys/types.h> /* for time_t */
|
||||
#include <string.h>
|
||||
#include <limits.h> /* for CHAR_BIT et al. */
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "errno.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef EINVAL
|
||||
# define EINVAL ERANGE
|
||||
#endif
|
||||
|
||||
#ifndef ENAMETOOLONG
|
||||
# define ENAMETOOLONG EINVAL
|
||||
#endif
|
||||
#ifndef ENOMEM
|
||||
# define ENOMEM EINVAL
|
||||
#endif
|
||||
#ifndef ENOTSUP
|
||||
# define ENOTSUP EINVAL
|
||||
#endif
|
||||
|
@ -122,22 +182,11 @@
|
|||
#endif
|
||||
|
||||
#if HAVE_GETTEXT
|
||||
#include "libintl.h"
|
||||
#include <libintl.h>
|
||||
#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
|
||||
#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 */
|
||||
|
||||
#ifndef HAVE_STRFTIME_L
|
||||
|
@ -148,31 +197,49 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef F_OK
|
||||
#define F_OK 0
|
||||
#endif /* !defined F_OK */
|
||||
#ifndef USG_COMPAT
|
||||
# ifndef _XOPEN_VERSION
|
||||
# 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 ALTZONE
|
||||
# if defined __sun || defined _M_XENIX
|
||||
# define ALTZONE 1
|
||||
# else
|
||||
# define ALTZONE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#endif /* !defined R_OK */
|
||||
|
||||
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
||||
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
||||
|
||||
/*
|
||||
** Define HAVE_STDINT_H's default value here, rather than at the
|
||||
** start, since __GLIBC__'s value depends on previously-included
|
||||
** files.
|
||||
** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
|
||||
** start, since __GLIBC__ and INTMAX_MAX's values depend on
|
||||
** previously-included files. glibc 2.1 and Solaris 10 and later have
|
||||
** stdint.h, even with pre-C99 compilers.
|
||||
*/
|
||||
#ifndef HAVE_STDINT_H
|
||||
#define HAVE_STDINT_H \
|
||||
(199901 <= __STDC_VERSION__ \
|
||||
|| 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
|
||||
|| __CYGWIN__)
|
||||
|| __CYGWIN__ || INTMAX_MAX)
|
||||
#endif /* !defined HAVE_STDINT_H */
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include "stdint.h"
|
||||
#include <stdint.h>
|
||||
#endif /* !HAVE_STDINT_H */
|
||||
|
||||
#ifndef HAVE_INTTYPES_H
|
||||
|
@ -208,14 +275,18 @@ typedef long int_fast64_t;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SCNdFAST64
|
||||
#ifndef PRIdFAST64
|
||||
# if INT_FAST64_MAX == LLONG_MAX
|
||||
# define SCNdFAST64 "lld"
|
||||
# define PRIdFAST64 "lld"
|
||||
# else
|
||||
# define SCNdFAST64 "ld"
|
||||
# define PRIdFAST64 "ld"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SCNdFAST64
|
||||
# define SCNdFAST64 PRIdFAST64
|
||||
#endif
|
||||
|
||||
#ifndef INT_FAST32_MAX
|
||||
# if INT_MAX >> 31 == 0
|
||||
typedef long int_fast32_t;
|
||||
|
@ -231,15 +302,19 @@ typedef int int_fast32_t;
|
|||
#ifndef INTMAX_MAX
|
||||
# ifdef LLONG_MAX
|
||||
typedef long long intmax_t;
|
||||
# define strtoimax strtoll
|
||||
# if HAVE_STRTOLL
|
||||
# define strtoimax strtoll
|
||||
# endif
|
||||
# define INTMAX_MAX LLONG_MAX
|
||||
# define INTMAX_MIN LLONG_MIN
|
||||
# else
|
||||
typedef long intmax_t;
|
||||
# define strtoimax strtol
|
||||
# define INTMAX_MAX LONG_MAX
|
||||
# define INTMAX_MIN LONG_MIN
|
||||
# endif
|
||||
# ifndef strtoimax
|
||||
# define strtoimax strtol
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PRIdMAX
|
||||
|
@ -250,6 +325,10 @@ typedef long intmax_t;
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef UINT_FAST32_MAX
|
||||
typedef unsigned long uint_fast32_t;
|
||||
#endif
|
||||
|
||||
#ifndef UINT_FAST64_MAX
|
||||
# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
|
||||
typedef unsigned long long uint_fast64_t;
|
||||
|
@ -289,19 +368,21 @@ typedef unsigned long uintmax_t;
|
|||
#define SIZE_MAX ((size_t) -1)
|
||||
#endif
|
||||
|
||||
#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
|
||||
# define ATTRIBUTE_CONST __attribute__ ((const))
|
||||
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
|
||||
# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
|
||||
#if 3 <= __GNUC__
|
||||
# define ATTRIBUTE_CONST __attribute__((const))
|
||||
# define ATTRIBUTE_MALLOC __attribute__((__malloc__))
|
||||
# define ATTRIBUTE_PURE __attribute__((__pure__))
|
||||
# define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
|
||||
#else
|
||||
# define ATTRIBUTE_CONST /* empty */
|
||||
# define ATTRIBUTE_MALLOC /* empty */
|
||||
# define ATTRIBUTE_PURE /* empty */
|
||||
# define ATTRIBUTE_FORMAT(spec) /* empty */
|
||||
#endif
|
||||
|
||||
#if !defined _Noreturn && __STDC_VERSION__ < 201112
|
||||
# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
|
||||
# define _Noreturn __attribute__ ((__noreturn__))
|
||||
# define _Noreturn __attribute__((__noreturn__))
|
||||
# else
|
||||
# define _Noreturn
|
||||
# endif
|
||||
|
@ -315,6 +396,23 @@ typedef unsigned long uintmax_t;
|
|||
** Workarounds for compilers/systems.
|
||||
*/
|
||||
|
||||
#ifndef EPOCH_LOCAL
|
||||
# define EPOCH_LOCAL 0
|
||||
#endif
|
||||
#ifndef EPOCH_OFFSET
|
||||
# define EPOCH_OFFSET 0
|
||||
#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
|
||||
** time_t type equivalent to T rather than the system-supplied time_t.
|
||||
|
@ -322,13 +420,24 @@ typedef unsigned long uintmax_t;
|
|||
** (e.g., time_t wider than 'long', or unsigned time_t) even on
|
||||
** typical platforms.
|
||||
*/
|
||||
#ifdef time_tz
|
||||
# ifdef LOCALTIME_IMPLEMENTATION
|
||||
#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
|
||||
# define TZ_TIME_T 1
|
||||
#else
|
||||
# define TZ_TIME_T 0
|
||||
#endif
|
||||
|
||||
#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
|
||||
static time_t sys_time(time_t *x) { return time(x); }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if TZ_TIME_T
|
||||
|
||||
typedef time_tz tz_time_t;
|
||||
|
||||
# undef asctime
|
||||
# define asctime tz_asctime
|
||||
# undef asctime_r
|
||||
# define asctime_r tz_asctime_r
|
||||
# undef ctime
|
||||
# define ctime tz_ctime
|
||||
# undef ctime_r
|
||||
|
@ -355,6 +464,8 @@ typedef time_tz tz_time_t;
|
|||
# define posix2time tz_posix2time
|
||||
# undef posix2time_z
|
||||
# define posix2time_z tz_posix2time_z
|
||||
# undef strftime
|
||||
# define strftime tz_strftime
|
||||
# undef time
|
||||
# define time tz_time
|
||||
# undef time2posix
|
||||
|
@ -375,12 +486,36 @@ typedef time_tz tz_time_t;
|
|||
# define tzfree tz_tzfree
|
||||
# undef tzset
|
||||
# define tzset tz_tzset
|
||||
# undef 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
|
||||
# if ALTZONE
|
||||
# undef altzone
|
||||
# define altzone tz_altzone
|
||||
# endif
|
||||
|
||||
char *asctime(struct tm const *);
|
||||
char *asctime_r(struct tm const *restrict, char *restrict);
|
||||
char *ctime(time_t const *);
|
||||
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_r(time_t const *restrict, struct tm *restrict);
|
||||
struct tm *localtime(time_t const *);
|
||||
|
@ -394,18 +529,26 @@ void tzset(void);
|
|||
extern char *asctime_r(struct tm const *restrict, char *restrict);
|
||||
#endif
|
||||
|
||||
#if !HAVE_POSIX_DECLS
|
||||
# ifdef USG_COMPAT
|
||||
# ifndef timezone
|
||||
extern long timezone;
|
||||
# endif
|
||||
# ifndef daylight
|
||||
extern int daylight;
|
||||
# endif
|
||||
#ifndef HAVE_DECL_ENVIRON
|
||||
# if defined environ || defined __USE_GNU
|
||||
# define HAVE_DECL_ENVIRON 1
|
||||
# else
|
||||
# define HAVE_DECL_ENVIRON 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined ALTZONE && !defined altzone
|
||||
#if !HAVE_DECL_ENVIRON
|
||||
extern char **environ;
|
||||
#endif
|
||||
|
||||
#if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
|
||||
extern char *tzname[];
|
||||
#endif
|
||||
#if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
|
||||
extern long timezone;
|
||||
extern int daylight;
|
||||
#endif
|
||||
#if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
|
||||
extern long altzone;
|
||||
#endif
|
||||
|
||||
|
@ -415,25 +558,22 @@ extern long altzone;
|
|||
*/
|
||||
|
||||
#ifdef STD_INSPIRED
|
||||
# if !defined tzsetwall || defined time_tz
|
||||
void tzsetwall(void);
|
||||
# endif
|
||||
# if !defined offtime || defined time_tz
|
||||
# if TZ_TIME_T || !defined offtime
|
||||
struct tm *offtime(time_t const *, long);
|
||||
# endif
|
||||
# if !defined timegm || defined time_tz
|
||||
# if TZ_TIME_T || !defined timegm
|
||||
time_t timegm(struct tm *);
|
||||
# endif
|
||||
# if !defined timelocal || defined time_tz
|
||||
# if TZ_TIME_T || !defined timelocal
|
||||
time_t timelocal(struct tm *);
|
||||
# endif
|
||||
# if !defined timeoff || defined time_tz
|
||||
# if TZ_TIME_T || !defined timeoff
|
||||
time_t timeoff(struct tm *, long);
|
||||
# endif
|
||||
# if !defined time2posix || defined time_tz
|
||||
# if TZ_TIME_T || !defined time2posix
|
||||
time_t time2posix(time_t);
|
||||
# endif
|
||||
# if !defined posix2time || defined time_tz
|
||||
# if TZ_TIME_T || !defined posix2time
|
||||
time_t posix2time(time_t);
|
||||
# endif
|
||||
#endif
|
||||
|
@ -467,10 +607,10 @@ time_t mktime_z(timezone_t restrict, struct tm *restrict);
|
|||
timezone_t tzalloc(char const *);
|
||||
void tzfree(timezone_t);
|
||||
# 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;
|
||||
# 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;
|
||||
# endif
|
||||
# endif
|
||||
|
@ -480,22 +620,16 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
|
|||
** Finally, some convenience items.
|
||||
*/
|
||||
|
||||
#if __STDC_VERSION__ < 199901
|
||||
#if HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#else
|
||||
# define true 1
|
||||
# define false 0
|
||||
# define bool int
|
||||
#else
|
||||
# include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#ifndef TYPE_BIT
|
||||
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
||||
#endif /* !defined TYPE_BIT */
|
||||
|
||||
#ifndef TYPE_SIGNED
|
||||
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
|
||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||
#endif /* !defined TYPE_SIGNED */
|
||||
|
||||
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
|
||||
|
||||
/* Max and min values of the integer type T, of which only the bottom
|
||||
|
@ -507,11 +641,34 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
|
|||
#define MINVAL(t, b) \
|
||||
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
|
||||
|
||||
/* The minimum and maximum finite time values. This assumes no padding. */
|
||||
static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
|
||||
static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
|
||||
/* The extreme time values, assuming no padding. */
|
||||
#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
|
||||
#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
|
||||
|
||||
/* The extreme time values. These are macros, not constants, so that
|
||||
any portability problems occur only when compiling .c files that use
|
||||
the macros, which is safer for applications that need only zdump and zic.
|
||||
This implementation assumes no padding if time_t is signed and
|
||||
either the compiler lacks support for _Generic or time_t is not one
|
||||
of the standard signed integer types. */
|
||||
#if HAVE_GENERIC
|
||||
# define TIME_T_MIN \
|
||||
_Generic((time_t) 0, \
|
||||
signed char: SCHAR_MIN, short: SHRT_MIN, \
|
||||
int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
|
||||
default: TIME_T_MIN_NO_PADDING)
|
||||
# define TIME_T_MAX \
|
||||
(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
|
||||
# define TIME_T_MIN TIME_T_MIN_NO_PADDING
|
||||
# define TIME_T_MAX TIME_T_MAX_NO_PADDING
|
||||
#endif
|
||||
|
||||
#ifndef INT_STRLEN_MAXIMUM
|
||||
/*
|
||||
** 302 / 1000 is log10(2.0) rounded up.
|
||||
** Subtract one for the sign bit if the type is signed;
|
||||
|
@ -521,13 +678,12 @@ static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
|
|||
#define INT_STRLEN_MAXIMUM(type) \
|
||||
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
|
||||
1 + TYPE_SIGNED(type))
|
||||
#endif /* !defined INT_STRLEN_MAXIMUM */
|
||||
|
||||
/*
|
||||
** INITIALIZE(x)
|
||||
*/
|
||||
|
||||
#ifdef lint
|
||||
#ifdef GCC_LINT
|
||||
# define INITIALIZE(x) ((x) = 0)
|
||||
#else
|
||||
# define INITIALIZE(x)
|
||||
|
@ -537,19 +693,30 @@ static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
|
|||
# define UNINIT_TRAP 0
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define UNREACHABLE() abort()
|
||||
#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
|
||||
# define UNREACHABLE() __builtin_unreachable()
|
||||
#elif defined __has_builtin
|
||||
# if __has_builtin(__builtin_unreachable)
|
||||
# define UNREACHABLE() __builtin_unreachable()
|
||||
# endif
|
||||
#endif
|
||||
#ifndef UNREACHABLE
|
||||
# define UNREACHABLE() ((void) 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** For the benefit of GNU folk...
|
||||
** '_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
** The default is to use gettext if available, and use MSGID otherwise.
|
||||
*/
|
||||
|
||||
#ifndef _
|
||||
#if HAVE_GETTEXT
|
||||
#define _(msgid) gettext(msgid)
|
||||
#else /* !HAVE_GETTEXT */
|
||||
#define _(msgid) msgid
|
||||
#endif /* !HAVE_GETTEXT */
|
||||
#endif /* !defined _ */
|
||||
|
||||
#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
|
||||
# define TZ_DOMAIN "tz"
|
||||
|
@ -562,24 +729,64 @@ char *asctime_r(struct tm const *, char *);
|
|||
char *ctime_r(time_t const *, char *);
|
||||
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
|
||||
|
||||
#ifndef YEARSPERREPEAT
|
||||
/* Handy macros that are independent of tzfile implementation. */
|
||||
|
||||
#define SECSPERMIN 60
|
||||
#define MINSPERHOUR 60
|
||||
#define HOURSPERDAY 24
|
||||
#define DAYSPERWEEK 7
|
||||
#define DAYSPERNYEAR 365
|
||||
#define DAYSPERLYEAR 366
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
|
||||
#endif /* !defined YEARSPERREPEAT */
|
||||
#define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1)
|
||||
#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
|
||||
#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
|
||||
|
||||
#define TM_SUNDAY 0
|
||||
#define TM_MONDAY 1
|
||||
#define TM_TUESDAY 2
|
||||
#define TM_WEDNESDAY 3
|
||||
#define TM_THURSDAY 4
|
||||
#define TM_FRIDAY 5
|
||||
#define TM_SATURDAY 6
|
||||
|
||||
#define TM_JANUARY 0
|
||||
#define TM_FEBRUARY 1
|
||||
#define TM_MARCH 2
|
||||
#define TM_APRIL 3
|
||||
#define TM_MAY 4
|
||||
#define TM_JUNE 5
|
||||
#define TM_JULY 6
|
||||
#define TM_AUGUST 7
|
||||
#define TM_SEPTEMBER 8
|
||||
#define TM_OCTOBER 9
|
||||
#define TM_NOVEMBER 10
|
||||
#define TM_DECEMBER 11
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
#define TM_WDAY_BASE TM_MONDAY
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY TM_THURSDAY
|
||||
|
||||
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||
|
||||
/*
|
||||
** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
|
||||
** Since everything in isleap is modulo 400 (or a factor of 400), we know that
|
||||
** isleap(y) == isleap(y % 400)
|
||||
** and so
|
||||
** isleap(a + b) == isleap((a + b) % 400)
|
||||
** or
|
||||
** isleap(a + b) == isleap(a % 400 + b % 400)
|
||||
** This is true even if % means modulo rather than Fortran remainder
|
||||
** (which is allowed by C89 but not by C99 or later).
|
||||
** We use this to avoid addition overflow problems.
|
||||
*/
|
||||
|
||||
#ifndef AVGSECSPERYEAR
|
||||
#define AVGSECSPERYEAR 31556952L
|
||||
#endif /* !defined AVGSECSPERYEAR */
|
||||
|
||||
#ifndef SECSPERREPEAT
|
||||
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
|
||||
#endif /* !defined SECSPERREPEAT */
|
||||
|
||||
#ifndef SECSPERREPEAT_BITS
|
||||
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
|
||||
#endif /* !defined SECSPERREPEAT_BITS */
|
||||
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Convert a broken-down time stamp to a string. */
|
||||
/* Convert a broken-down timestamp to a string. */
|
||||
|
||||
/* Copyright 1989 The Regents of the University of California.
|
||||
All rights reserved.
|
||||
|
@ -35,9 +35,13 @@
|
|||
|
||||
#include "private.h"
|
||||
|
||||
#include "tzfile.h"
|
||||
#include "fcntl.h"
|
||||
#include "locale.h"
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef DEPRECATE_TWO_DIGIT_YEARS
|
||||
# define DEPRECATE_TWO_DIGIT_YEARS false
|
||||
#endif
|
||||
|
||||
#if defined(__BIONIC__)
|
||||
|
||||
|
@ -45,6 +49,7 @@
|
|||
#if defined(__LP64__)
|
||||
#define time64_t time_t
|
||||
#define mktime64 mktime
|
||||
#define localtime64_r localtime_r
|
||||
#else
|
||||
#include <time64.h>
|
||||
#endif
|
||||
|
@ -88,7 +93,7 @@ static const struct lc_time_T C_time_locale = {
|
|||
|
||||
/*
|
||||
** x_fmt
|
||||
** C99 requires this format.
|
||||
** C99 and later require this format.
|
||||
** Using just numbers (as here) makes Quakers happier;
|
||||
** it's also compatible with SVR4.
|
||||
*/
|
||||
|
@ -96,7 +101,7 @@ static const struct lc_time_T C_time_locale = {
|
|||
|
||||
/*
|
||||
** c_fmt
|
||||
** C99 requires this format.
|
||||
** C99 and later require this format.
|
||||
** Previously this code used "%D %X", but we now conform to C99.
|
||||
** Note that
|
||||
** "%a %b %d %H:%M:%S %Y"
|
||||
|
@ -114,25 +119,18 @@ static const struct lc_time_T C_time_locale = {
|
|||
"%a %b %e %H:%M:%S %Z %Y"
|
||||
};
|
||||
|
||||
enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
|
||||
|
||||
static char * _add(const char *, char *, const char *, int);
|
||||
static char * _conv(int, const char *, char *, const char *);
|
||||
static char * _fmt(const char *, const struct tm *, char *, const char *,
|
||||
int *);
|
||||
enum warn *);
|
||||
static char * _yconv(int, int, bool, bool, char *, const char *, int);
|
||||
|
||||
#if !HAVE_POSIX_DECLS
|
||||
extern char * tzname[];
|
||||
#endif
|
||||
|
||||
#ifndef YEAR_2000_NAME
|
||||
#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
|
||||
#endif /* !defined YEAR_2000_NAME */
|
||||
|
||||
#define IN_NONE 0
|
||||
#define IN_SOME 1
|
||||
#define IN_THIS 2
|
||||
#define IN_ALL 3
|
||||
|
||||
#if HAVE_STRFTIME_L
|
||||
size_t
|
||||
strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
|
||||
|
@ -149,18 +147,19 @@ size_t
|
|||
strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
|
||||
{
|
||||
char * p;
|
||||
int warn;
|
||||
int saved_errno = errno;
|
||||
enum warn warn = IN_NONE;
|
||||
|
||||
tzset();
|
||||
warn = IN_NONE;
|
||||
p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
|
||||
#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
|
||||
if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
|
||||
p = _fmt(format, t, s, s + maxsize, &warn);
|
||||
if (!p) {
|
||||
errno = EOVERFLOW;
|
||||
return 0;
|
||||
}
|
||||
if (DEPRECATE_TWO_DIGIT_YEARS
|
||||
&& warn != IN_NONE && getenv(YEAR_2000_NAME)) {
|
||||
fprintf(stderr, "\n");
|
||||
if (format == NULL)
|
||||
fprintf(stderr, "NULL strftime format ");
|
||||
else fprintf(stderr, "strftime format \"%s\" ",
|
||||
format);
|
||||
fprintf(stderr, "strftime format \"%s\" ", format);
|
||||
fprintf(stderr, "yields only two digits of years in ");
|
||||
if (warn == IN_SOME)
|
||||
fprintf(stderr, "some locales");
|
||||
|
@ -169,10 +168,12 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
|
|||
else fprintf(stderr, "all locales");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
|
||||
if (p == s + maxsize)
|
||||
if (p == s + maxsize) {
|
||||
errno = ERANGE;
|
||||
return 0;
|
||||
}
|
||||
*p = '\0';
|
||||
errno = saved_errno;
|
||||
return p - s;
|
||||
}
|
||||
|
||||
|
@ -191,7 +192,7 @@ static char *getformat(int modifier, char *normal, char *underscore,
|
|||
|
||||
static char *
|
||||
_fmt(const char *format, const struct tm *t, char *pt,
|
||||
const char *ptlim, int *warnp)
|
||||
const char *ptlim, enum warn *warnp)
|
||||
{
|
||||
for ( ; *format; ++format) {
|
||||
if (*format == '%') {
|
||||
|
@ -239,7 +240,7 @@ label:
|
|||
continue;
|
||||
case 'c':
|
||||
{
|
||||
int warn2 = IN_SOME;
|
||||
enum warn warn2 = IN_SOME;
|
||||
|
||||
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
|
||||
if (warn2 == IN_ALL)
|
||||
|
@ -257,12 +258,12 @@ label:
|
|||
case 'E':
|
||||
case 'O':
|
||||
/*
|
||||
** C99 locale modifiers.
|
||||
** Locale modifiers of C99 and later.
|
||||
** The sequences
|
||||
** %Ec %EC %Ex %EX %Ey %EY
|
||||
** %Od %oe %OH %OI %Om %OM
|
||||
** %OS %Ou %OU %OV %Ow %OW %Oy
|
||||
** are supposed to provide alternate
|
||||
** are supposed to provide alternative
|
||||
** representations.
|
||||
*/
|
||||
goto label;
|
||||
|
@ -356,11 +357,17 @@ label:
|
|||
|
||||
tm = *t;
|
||||
mkt = mktime64(&tm);
|
||||
if (TYPE_SIGNED(time64_t))
|
||||
snprintf(buf, sizeof(buf), "%"PRIdMAX,
|
||||
(intmax_t) mkt);
|
||||
else snprintf(buf, sizeof(buf), "%"PRIuMAX,
|
||||
(uintmax_t) mkt);
|
||||
/* There is no portable, definitive
|
||||
test for whether whether mktime
|
||||
succeeded, so treat (time_t) -1 as
|
||||
the success that it might be. */
|
||||
if (TYPE_SIGNED(time64_t)) {
|
||||
intmax_t n = mkt;
|
||||
sprintf(buf, "%"PRIdMAX, n);
|
||||
} else {
|
||||
uintmax_t n = mkt;
|
||||
sprintf(buf, "%"PRIuMAX, n);
|
||||
}
|
||||
pt = _add(buf, pt, ptlim, modifier);
|
||||
}
|
||||
continue;
|
||||
|
@ -392,7 +399,7 @@ label:
|
|||
** (01-53)."
|
||||
** (ado, 1993-05-24)
|
||||
**
|
||||
** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
|
||||
** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
|
||||
** "Week 01 of a year is per definition the first week which has the
|
||||
** Thursday in this year, which is equivalent to the week which contains
|
||||
** the fourth day of January. In other words, the first week of a new year
|
||||
|
@ -494,7 +501,7 @@ label:
|
|||
continue;
|
||||
case 'x':
|
||||
{
|
||||
int warn2 = IN_SOME;
|
||||
enum warn warn2 = IN_SOME;
|
||||
|
||||
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
|
||||
if (warn2 == IN_ALL)
|
||||
|
@ -533,29 +540,30 @@ label:
|
|||
pt = _add(zone, pt, ptlim, modifier);
|
||||
}
|
||||
// END: Android-changed.
|
||||
#else
|
||||
#elif HAVE_TZNAME
|
||||
if (t->tm_isdst >= 0)
|
||||
pt = _add(tzname[t->tm_isdst != 0],
|
||||
pt, ptlim);
|
||||
#endif
|
||||
/*
|
||||
** C99 says that %Z must be replaced by the
|
||||
** empty string if the time zone is not
|
||||
** C99 and later say that %Z must be
|
||||
** replaced by the empty string if the
|
||||
** time zone abbreviation is not
|
||||
** determinable.
|
||||
*/
|
||||
continue;
|
||||
case 'z':
|
||||
#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
|
||||
{
|
||||
long diff;
|
||||
char const * sign;
|
||||
bool negative;
|
||||
|
||||
if (t->tm_isdst < 0)
|
||||
continue;
|
||||
#ifdef TM_GMTOFF
|
||||
# ifdef TM_GMTOFF
|
||||
diff = t->TM_GMTOFF;
|
||||
#else /* !defined TM_GMTOFF */
|
||||
# else
|
||||
/*
|
||||
** C99 says that the UT offset must
|
||||
** C99 and later say that the UT offset must
|
||||
** be computed by looking only at
|
||||
** tm_isdst. This requirement is
|
||||
** incorrect, since it means the code
|
||||
|
@ -563,30 +571,44 @@ label:
|
|||
** altzone and timezone), and the
|
||||
** magic might not have the correct
|
||||
** offset. Doing things correctly is
|
||||
** tricky and requires disobeying C99;
|
||||
** tricky and requires disobeying the standard;
|
||||
** see GNU C strftime for details.
|
||||
** For now, punt and conform to the
|
||||
** standard, even though it's incorrect.
|
||||
**
|
||||
** C99 says that %z must be replaced by the
|
||||
** empty string if the time zone is not
|
||||
** C99 and later say that %z must be replaced by
|
||||
** the empty string if the time zone is not
|
||||
** determinable, so output nothing if the
|
||||
** appropriate variables are not available.
|
||||
*/
|
||||
if (t->tm_isdst < 0)
|
||||
continue;
|
||||
if (t->tm_isdst == 0)
|
||||
#ifdef USG_COMPAT
|
||||
# if USG_COMPAT
|
||||
diff = -timezone;
|
||||
#else /* !defined USG_COMPAT */
|
||||
# else
|
||||
continue;
|
||||
#endif /* !defined USG_COMPAT */
|
||||
# endif
|
||||
else
|
||||
#ifdef ALTZONE
|
||||
# if ALTZONE
|
||||
diff = -altzone;
|
||||
#else /* !defined ALTZONE */
|
||||
# else
|
||||
continue;
|
||||
#endif /* !defined ALTZONE */
|
||||
#endif /* !defined TM_GMTOFF */
|
||||
if (diff < 0) {
|
||||
# endif
|
||||
# endif
|
||||
negative = diff < 0;
|
||||
if (diff == 0) {
|
||||
#ifdef TM_ZONE
|
||||
negative = t->TM_ZONE[0] == '-';
|
||||
#else
|
||||
negative = t->tm_isdst < 0;
|
||||
# if HAVE_TZNAME
|
||||
if (tzname[t->tm_isdst != 0][0] == '-')
|
||||
negative = true;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
if (negative) {
|
||||
sign = "-";
|
||||
diff = -diff;
|
||||
} else sign = "+";
|
||||
|
@ -596,6 +618,7 @@ label:
|
|||
(diff % MINSPERHOUR);
|
||||
pt = _conv(diff, getformat(modifier, "04", " 4", " ", "04"), pt, ptlim);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
case '+':
|
||||
pt = _fmt(Locale->date_fmt, t, pt, ptlim,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* Layout and location of TZif files. */
|
||||
|
||||
#ifndef TZFILE_H
|
||||
|
||||
#define TZFILE_H
|
||||
|
@ -20,17 +22,20 @@
|
|||
*/
|
||||
|
||||
#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 */
|
||||
|
||||
#ifndef TZDEFAULT
|
||||
#define TZDEFAULT "localtime"
|
||||
#define TZDEFAULT "/etc/localtime"
|
||||
#endif /* !defined TZDEFAULT */
|
||||
|
||||
#ifndef TZDEFRULES
|
||||
#define TZDEFRULES "posixrules"
|
||||
#endif /* !defined TZDEFRULES */
|
||||
|
||||
|
||||
/* See Internet RFC 8536 for more details about the following format. */
|
||||
|
||||
/*
|
||||
** Each file begins with. . .
|
||||
*/
|
||||
|
@ -39,9 +44,9 @@
|
|||
|
||||
struct tzhead {
|
||||
char tzh_magic[4]; /* TZ_MAGIC */
|
||||
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
||||
char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */
|
||||
char tzh_reserved[15]; /* reserved; must be zero */
|
||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||
char tzh_timecnt[4]; /* coded number of transition times */
|
||||
|
@ -64,14 +69,15 @@ struct tzhead {
|
|||
** one (char [4]) total correction after above
|
||||
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
|
||||
** time is standard time, if 0,
|
||||
** transition time is wall clock time
|
||||
** if absent, transition times are
|
||||
** assumed to be wall clock time
|
||||
** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
|
||||
** time is UT, if 0,
|
||||
** transition time is local time
|
||||
** if absent, transition times are
|
||||
** transition time is local (wall clock)
|
||||
** time; if absent, transition times are
|
||||
** assumed to be local time
|
||||
** tzh_ttisutcnt (char)s indexed by type; if 1, transition
|
||||
** time is UT, if 0, transition time is
|
||||
** local time; if absent, transition
|
||||
** times are assumed to be local time.
|
||||
** When this is 1, the corresponding
|
||||
** std/wall indicator must also be 1.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
|
@ -184,6 +184,24 @@ TEST(time, mktime_EOVERFLOW) {
|
|||
ASSERT_EQ(EOVERFLOW, errno);
|
||||
}
|
||||
|
||||
TEST(time, mktime_invalid_tm_TZ_combination) {
|
||||
setenv("TZ", "UTC", 1);
|
||||
|
||||
struct tm t;
|
||||
memset(&t, 0, sizeof(tm));
|
||||
t.tm_year = 2022 - 1900;
|
||||
t.tm_mon = 11;
|
||||
t.tm_mday = 31;
|
||||
// UTC does not observe DST
|
||||
t.tm_isdst = 1;
|
||||
|
||||
errno = 0;
|
||||
|
||||
EXPECT_EQ(static_cast<time_t>(-1), mktime(&t));
|
||||
// mktime sets errno to EOVERFLOW if result is unrepresentable.
|
||||
EXPECT_EQ(EOVERFLOW, errno);
|
||||
}
|
||||
|
||||
TEST(time, strftime) {
|
||||
setenv("TZ", "UTC", 1);
|
||||
|
||||
|
@ -206,6 +224,24 @@ TEST(time, strftime) {
|
|||
EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
|
||||
}
|
||||
|
||||
TEST(time, strftime_second_before_epoch) {
|
||||
setenv("TZ", "UTC", 1);
|
||||
|
||||
struct tm t;
|
||||
memset(&t, 0, sizeof(tm));
|
||||
t.tm_year = 1969 - 1900;
|
||||
t.tm_mon = 11;
|
||||
t.tm_mday = 31;
|
||||
t.tm_hour = 23;
|
||||
t.tm_min = 59;
|
||||
t.tm_sec = 59;
|
||||
|
||||
char buf[64];
|
||||
|
||||
EXPECT_EQ(2U, strftime(buf, sizeof(buf), "%s", &t));
|
||||
EXPECT_STREQ("-1", buf);
|
||||
}
|
||||
|
||||
TEST(time, strftime_null_tm_zone) {
|
||||
// Netflix on Nexus Player wouldn't start (http://b/25170306).
|
||||
struct tm t;
|
||||
|
|
Loading…
Reference in a new issue