From 41db8ca9db05facd02607c875e089f625ef045ed Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Mon, 18 Oct 2004 22:33:44 +0000 Subject: Update to tzcode2004e from elsie.nci.nih.gov --- lib/libc/time/asctime.c | 99 +++++++++++++---- lib/libc/time/ctime.3 | 36 ++++-- lib/libc/time/localtime.c | 72 +++++++++--- lib/libc/time/private.h | 16 ++- lib/libc/time/strftime.c | 53 ++++++--- lib/libc/time/tz-link.htm | 277 +++++++++++++++++++++++++++++----------------- lib/libc/time/zdump.c | 76 +++++++++---- 7 files changed, 438 insertions(+), 191 deletions(-) diff --git a/lib/libc/time/asctime.c b/lib/libc/time/asctime.c index 15bcb448cac..5e22f919b72 100644 --- a/lib/libc/time/asctime.c +++ b/lib/libc/time/asctime.c @@ -4,8 +4,8 @@ */ #if defined(LIBC_SCCS) && !defined(lint) && !defined(NOID) -static char elsieid[] = "@(#)asctime.c 7.9"; -static char rcsid[] = "$OpenBSD: asctime.c,v 1.7 2000/01/06 08:24:17 d Exp $"; +static char elsieid[] = "@(#)asctime.c 7.22"; +static char rcsid[] = "$OpenBSD: asctime.c,v 1.8 2004/10/18 22:33:43 millert Exp $"; #endif /* LIBC_SCCS and not lint */ /*LINTLIBRARY*/ @@ -14,14 +14,51 @@ static char rcsid[] = "$OpenBSD: asctime.c,v 1.7 2000/01/06 08:24:17 d Exp $"; #include "tzfile.h" #include "thread_private.h" +#if STRICTLY_STANDARD_ASCTIME +#define ASCTIME_FMT "%.3s %.3s%3d %.2d:%.2d:%.2d %ld\n" +#define ASCTIME_FMT_B ASCTIME_FMT +#else /* !STRICTLY_STANDARD_ASCTIME */ /* -** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, Second Edition, 1996-07-12. +** Some systems only handle "%.2d"; others only handle "%02d"; +** "%02.2d" makes (most) everybody happy. +** At least some versions of gcc warn about the %02.2d; ignore the warning. */ +/* +** All years associated with 32-bit time_t values are exactly four digits long; +** some years associated with 64-bit time_t values are not. +** Vintage programs are coded for years that are always four digits long +** and may assume that the newline always lands in the same place. +** For years that are less than four digits, we pad the output with +** spaces before the newline to get the newline in the traditional place. +*/ +#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4ld\n" +/* +** For years that are more than four digits we put extra spaces before the year +** so that code trying to overwrite the newline won't end up overwriting +** a digit within a year and truncating the year (operating on the assumption +** that no output is better than wrong output). +*/ +#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %ld\n" +#endif /* !STRICTLY_STANDARD_ASCTIME */ -char * -asctime_r(timeptr, buf) +#define STD_ASCTIME_BUF_SIZE 26 +/* +** Big enough for something such as +** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n +** (two three-character abbreviations, five strings denoting integers, +** seven explicit spaces, two explicit colons, a newline, +** and a trailing ASCII nul). +** The values above are for systems where an int is 32 bits and are provided +** as an example; the define below calculates the maximum for the system at +** hand. +*/ +#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1) + +static char * +asctime3(timeptr, buf, bufsize) register const struct tm * timeptr; char * buf; +int bufsize; { static const char wday_name[][3] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" @@ -32,7 +69,8 @@ char * buf; }; register const char * wn; register const char * mn; - int size; + long year; + int len; if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK) wn = "???"; @@ -40,40 +78,55 @@ char * buf; if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR) mn = "???"; else mn = mon_name[timeptr->tm_mon]; - /* - ** The X3J11-suggested format is - ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n" - ** Since the .2 in 02.2d is ignored, we drop it. - */ - /* - * P1003 8.3.5.2 says that asctime_r() can only assume at most - * a 26 byte buffer. *XXX* - */ - size = snprintf(buf, 26, "%.3s %.3s%3d %02d:%02d:%02d %d\n", + year = timeptr->tm_year + (long) TM_YEAR_BASE; + len = snprintf(buf, bufsize, + ((year >= -999 && year <= 9999) ? ASCTIME_FMT : ASCTIME_FMT_B), wn, mn, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, TM_YEAR_BASE + timeptr->tm_year); - if (size >= 26) + if (len < bufsize) { + return buf; + } else { +#ifdef EOVERFLOW + errno = EOVERFLOW; +#else /* !defined EOVERFLOW */ + errno = EINVAL; +#endif /* !defined EOVERFLOW */ return NULL; - return buf; + } +} + +/* +** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition. +*/ + +char * +asctime_r(timeptr, buf) +register const struct tm * timeptr; +char * buf; +{ + /* + ** P1003 8.3.5.2 says that asctime_r() can only assume at most + ** a 26 byte buffer. + */ + return asctime3(timeptr, buf, STD_ASCTIME_BUF_SIZE); } /* -** A la X3J11, with core dump avoidance. +** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition. */ char * asctime(timeptr) const struct tm * timeptr; { - /* asctime_r won't exceed this buffer: */ - static char result[26]; + static char result[MAX_ASCTIME_BUF_SIZE]; _THREAD_PRIVATE_KEY(asctime); - char *resultp = (char*) _THREAD_PRIVATE(asctime, result, NULL); + char *resultp = (char *)_THREAD_PRIVATE(asctime, result, NULL); if (resultp == NULL) return NULL; else - return asctime_r(timeptr, resultp); + return asctime3(timeptr, resultp, sizeof(result)); } diff --git a/lib/libc/time/ctime.3 b/lib/libc/time/ctime.3 index 5fe445196ab..d7bc31615f2 100644 --- a/lib/libc/time/ctime.3 +++ b/lib/libc/time/ctime.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ctime.3,v 1.28 2003/07/07 15:38:38 jmc Exp $ +.\" $OpenBSD: ctime.3,v 1.29 2004/10/18 22:33:43 millert Exp $ .\" .\" .Dd February 16, 1999 @@ -59,12 +59,19 @@ pointed to by representing the time in seconds since 00:00:00 UTC, 1970-01-01, and returns a pointer to a -26-character string -of the form +string of the form .Pp .Dl Thu Nov 24 18:22:48 1986\en .Pp -All the fields have constant width. +Years requiring fewer than four characters are padded with trailing spaces. +For years longer than four characters, the string is of the form +.Pp +.Dl Thu Nov 24 18:22:48\ \ \ \ \ 81986\en +.Pp +with five spaces before the year. +This unusual format is designed to make it less likely that older +software that expects exactly 26 bytes of output will mistakenly output +misleading values for out-of-range years. .Pp The .Fn ctime_r @@ -130,10 +137,9 @@ the reentrant version is not required to set .Fn asctime converts a time value contained in a .Li tm -structure to a 26-character string, +structure to a string, as shown in the above example, -and returns a pointer -to the string. +and returns a pointer to the string. .Fn asctime_r uses the buffer pointed to by .Fa buf @@ -285,6 +291,20 @@ will also be overwritten at the next call (and by calls to .Fn tzset ) . .Pp +.Fn asctime +and +.Fn ctime +behave strangely for years before 1000 or after 9999. +The 1989 and 1999 editions of the C Standard say +that years from \-99 through 999 are converted without +extra spaces, but this conflicts with longstanding +tradition and with this implementation. +Traditional implementations of these two functions are +restricted to years in the range 1900 through 2099. +To avoid this portability mess, new programs should use +.Fn strftime +instead. +.Pp The default system time zone may be set by running .Dq Li zic -l timezone as the superuser. @@ -292,6 +312,6 @@ as the superuser. Avoid using out-of-range values with .Fn mktime when setting up lunch with promptness sticklers in Riyadh. -.\" based on @(#)newctime.3 7.14 +.\" based on @(#)newctime.3 7.16 .\" This file is in the public domain, so clarified as of .\" 2003-02-14 by Arthur David Olson (arthur_david_olson@nih.gov). diff --git a/lib/libc/time/localtime.c b/lib/libc/time/localtime.c index 59615a97971..e9bb299afe9 100644 --- a/lib/libc/time/localtime.c +++ b/lib/libc/time/localtime.c @@ -4,8 +4,8 @@ */ #if defined(LIBC_SCCS) && !defined(lint) && !defined(NOID) -static char elsieid[] = "@(#)localtime.c 7.78"; -static char rcsid[] = "$OpenBSD: localtime.c,v 1.24 2004/06/28 14:47:41 millert Exp $"; +static char elsieid[] = "@(#)localtime.c 7.80"; +static char rcsid[] = "$OpenBSD: localtime.c,v 1.25 2004/10/18 22:33:43 millert Exp $"; #endif /* LIBC_SCCS and not lint */ /* @@ -134,6 +134,9 @@ static void gmtsub P((const time_t * timep, long offset, static void localsub P((const time_t * timep, long offset, struct tm * tmp)); static int increment_overflow P((int * number, int delta)); +static int long_increment_overflow P((long * number, int delta)); +static int long_normalize_overflow P((long * tensptr, + int * unitsptr, int base)); static int normalize_overflow P((int * tensptr, int * unitsptr, int base)); static void settzname P((void)); @@ -1183,7 +1186,7 @@ register struct tm * const tmp; register const struct lsinfo * lp; register long days; register long rem; - register int y; + register long y; register int yleap; register const int * ip; register long corr; @@ -1252,7 +1255,7 @@ register struct tm * const tmp; y = EPOCH_YEAR; #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { - register int newy; + register long newy; newy = y + days / DAYSPERNYEAR; if (days < 0) @@ -1327,6 +1330,18 @@ int delta; return (*number < number0) != (delta < 0); } +static int +long_increment_overflow(number, delta) +long * number; +int delta; +{ + long number0; + + number0 = *number; + *number += delta; + return (*number < number0) != (delta < 0); +} + static int normalize_overflow(tensptr, unitsptr, base) int * const tensptr; @@ -1342,6 +1357,21 @@ const int base; return increment_overflow(tensptr, tensdelta); } +static int +long_normalize_overflow(tensptr, unitsptr, base) +long * const tensptr; +int * const unitsptr; +const int base; +{ + register int tensdelta; + + tensdelta = (*unitsptr >= 0) ? + (*unitsptr / base) : + (-1 - (-1 - *unitsptr) / base); + *unitsptr -= tensdelta * base; + return long_increment_overflow(tensptr, tensdelta); +} + static int tmcomp(atmp, btmp) register const struct tm * const atmp; @@ -1369,8 +1399,10 @@ const int do_norm_secs; register const struct state * sp; register int dir; register int bits; - register int i, j ; + register int i, j; register int saved_seconds; + register long li; + long y; time_t newt; time_t t; struct tm yourtm, mytm; @@ -1386,42 +1418,46 @@ const int do_norm_secs; return WRONG; if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) return WRONG; - if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)) + y = yourtm.tm_year; + if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) return WRONG; /* - ** Turn yourtm.tm_year into an actual year number for now. + ** Turn y into an actual year number for now. ** It is converted back to an offset from TM_YEAR_BASE later. */ - if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE)) + if (long_increment_overflow(&y, TM_YEAR_BASE)) return WRONG; while (yourtm.tm_mday <= 0) { - if (increment_overflow(&yourtm.tm_year, -1)) + if (long_increment_overflow(&y, -1)) return WRONG; - i = yourtm.tm_year + (1 < yourtm.tm_mon); - yourtm.tm_mday += year_lengths[isleap(i)]; + li = y + (1 < yourtm.tm_mon); + yourtm.tm_mday += year_lengths[isleap(li)]; } while (yourtm.tm_mday > DAYSPERLYEAR) { - i = yourtm.tm_year + (1 < yourtm.tm_mon); - yourtm.tm_mday -= year_lengths[isleap(i)]; - if (increment_overflow(&yourtm.tm_year, 1)) + li = y + (1 < yourtm.tm_mon); + yourtm.tm_mday -= year_lengths[isleap(li)]; + if (long_increment_overflow(&y, 1)) return WRONG; } for ( ; ; ) { - i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon]; + i = mon_lengths[isleap(y)][yourtm.tm_mon]; if (yourtm.tm_mday <= i) break; yourtm.tm_mday -= i; if (++yourtm.tm_mon >= MONSPERYEAR) { yourtm.tm_mon = 0; - if (increment_overflow(&yourtm.tm_year, 1)) + if (long_increment_overflow(&y, 1)) return WRONG; } } - if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE)) + if (long_increment_overflow(&y, -TM_YEAR_BASE)) return WRONG; + yourtm.tm_year = y; + if (yourtm.tm_year != y) + return WRONG; if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) saved_seconds = 0; - else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) { + else if (y + TM_YEAR_BASE < EPOCH_YEAR) { /* ** We can't set tm_sec to 0, because that might push the ** time below the minimum representable time. diff --git a/lib/libc/time/private.h b/lib/libc/time/private.h index b1b6b10e0ab..72a1a785323 100644 --- a/lib/libc/time/private.h +++ b/lib/libc/time/private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: private.h,v 1.15 2004/06/28 14:47:41 millert Exp $ */ +/* $OpenBSD: private.h,v 1.16 2004/10/18 22:33:43 millert Exp $ */ #ifndef PRIVATE_H #define PRIVATE_H @@ -33,7 +33,7 @@ #if 0 #ifndef lint #ifndef NOID -static char privatehid[] = "@(#)private.h 7.53"; +static char privatehid[] = "@(#)private.h 7.54"; #endif /* !defined NOID */ #endif /* !defined lint */ #endif @@ -191,6 +191,7 @@ static char privatehid[] = "@(#)private.h 7.53"; #endif /* !defined FILENAME_MAX */ +#if 0 /* ** SunOS 4.1.1 libraries lack remove. */ @@ -200,7 +201,6 @@ extern int unlink P((const char * filename)); #define remove unlink #endif /* !defined remove */ -#if 0 /* ** Some ancient errno.h implementations don't declare errno. ** But some newer errno.h implementations define it as a macro. @@ -209,6 +209,16 @@ extern int unlink P((const char * filename)); #ifndef errno extern int errno; #endif /* !defined errno */ + +/* +** Some time.h implementations don't declare asctime_r. +** Others might define it as a macro. +** Fix the former without affecting the latter. +*/ + +#ifndef asctime_r +extern char * asctime_r(); +#endif #endif /* diff --git a/lib/libc/time/strftime.c b/lib/libc/time/strftime.c index 9be6718fedd..8246302c69d 100644 --- a/lib/libc/time/strftime.c +++ b/lib/libc/time/strftime.c @@ -1,6 +1,12 @@ +/* +** XXX To do: figure out correct (as distinct from standard-mandated) +** output for "two digits of year" and "century" formats when +** the year is negative or less than 100. --ado, 2004-09-09 +*/ + #if defined(LIBC_SCCS) && !defined(lint) && !defined(NOID) static char elsieid[] = "@(#)strftime.c 7.64"; -static char *rcsid = "$OpenBSD: strftime.c,v 1.13 2003/06/04 21:47:58 deraadt Exp $"; +static char *rcsid = "$OpenBSD: strftime.c,v 1.14 2004/10/18 22:33:43 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include "private.h" @@ -120,6 +126,7 @@ static const struct lc_time_T C_time_locale = { static char * _add P((const char *, char *, const char *)); static char * _conv P((int, const char *, char *, const char *)); +static char * _lconv P((long, const char *, char *, const char *)); static char * _fmt P((const char *, const struct tm *, char *, const char *, int *)); size_t strftime P((char *, size_t, const char *, const struct tm *)); @@ -225,7 +232,8 @@ label: ** something completely different. ** (ado, 1993-05-24) */ - pt = _conv((t->tm_year + TM_YEAR_BASE) / 100, + pt = _conv((int) ((t->tm_year + + (long) TM_YEAR_BASE) / 100), "%02d", pt, ptlim); continue; case 'c': @@ -394,12 +402,13 @@ label: ** (ado, 1996-01-02) */ { - int year; + long year; int yday; int wday; int w; - year = t->tm_year + TM_YEAR_BASE; + year = t->tm_year; + year += TM_YEAR_BASE; yday = t->tm_yday; wday = t->tm_wday; for ( ; ; ) { @@ -441,20 +450,20 @@ label: DAYSPERNYEAR; } #ifdef XPG4_1994_04_09 - if ((w == 52 - && t->tm_mon == TM_JANUARY) - || (w == 1 - && t->tm_mon == TM_DECEMBER)) - w = 53; + if ((w == 52 && + t->tm_mon == TM_JANUARY) || + (w == 1 && + t->tm_mon == TM_DECEMBER)) + w = 53; #endif /* defined XPG4_1994_04_09 */ if (*format == 'V') pt = _conv(w, "%02d", pt, ptlim); else if (*format == 'g') { *warnp = IN_ALL; - pt = _conv(year % 100, "%02d", - pt, ptlim); - } else pt = _conv(year, "%04d", + pt = _conv((int) (year % 100), + "%02d", pt, ptlim); + } else pt = _lconv(year, "%04ld", pt, ptlim); } continue; @@ -492,12 +501,13 @@ label: continue; case 'y': *warnp = IN_ALL; - pt = _conv((t->tm_year + TM_YEAR_BASE) % 100, + pt = _conv((int) ((t->tm_year + + (long) TM_YEAR_BASE) % 100), "%02d", pt, ptlim); continue; case 'Y': - pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d", - pt, ptlim); + pt = _lconv(t->tm_year + (long) TM_YEAR_BASE, + "%04ld", pt, ptlim); continue; case 'Z': #ifdef TM_ZONE @@ -600,6 +610,19 @@ const char * const ptlim; return _add(buf, pt, ptlim); } +static char * +_lconv(n, format, pt, ptlim) +const long n; +const char * const format; +char * const pt; +const char * const ptlim; +{ + char buf[INT_STRLEN_MAXIMUM(long) + 1]; + + (void) snprintf(buf, sizeof buf, format, n); + return _add(buf, pt, ptlim); +} + static char * _add(str, pt, ptlim) const char * str; diff --git a/lib/libc/time/tz-link.htm b/lib/libc/time/tz-link.htm index 0e630730070..e55d1f6a288 100644 --- a/lib/libc/time/tz-link.htm +++ b/lib/libc/time/tz-link.htm @@ -9,7 +9,7 @@ - + @@ -19,35 +19,38 @@

Sources for Time Zone and Daylight Saving Time Data

-@(#)tz-link.htm 7.42 +@(#)tz-link.htm 7.44

Please send corrections to this web page to the -time zone mailing list. -

+time zone mailing list.

The tz database

The public-domain time zone database contains code and data that represent the history of local time for many representative locations around the globe. It is updated periodically to reflect changes made by political bodies -to UTC offsets and daylight-saving rules. +to UTC +offsets and daylight-saving rules. This database (often called tz or zoneinfo) is used by several implementations, including -the GNU C Library used in -GNU/Linux, +the +GNU +C Library used in +GNU/Linux, FreeBSD, NetBSD, OpenBSD, Cygwin, -DJGPP, +DJGPP, HP-UX, IRIX, Mac OS X, OpenVMS, Solaris, -Tru64, and +Tru64, and UnixWare.

Each location in the database represents a national region where all @@ -55,24 +58,30 @@ clocks keeping local time have agreed since 1970. Locations are identified by continent or ocean and then by the name of the location, which is typically the largest city within the region. For example, America/New_York -represents most of the US eastern time zone; +represents most of the US eastern time zone; America/Indianapolis represents most of Indiana, which -uses eastern time without daylight saving time (DST); +uses eastern time without daylight saving time (DST); America/Detroit represents most of Michigan, which uses -eastern time but with different DST rules in 1975; +eastern time but with different DST rules in 1975; and other entries represent smaller regions like Starke County, Kentucky, which switched from central to eastern time in 1991. -To use the database, set the TZ environment variable to +To use the database on an extended POSIX +implementation set the TZ environment variable to the location's full name, e.g., TZ="America/New_York".

In the tz database's -FTP distribution, +FTP distribution the code is in the file tzcodeC.tar.gz, where C is the code's version; similarly, the data are in tzdataD.tar.gz, where D is the data's version. The following shell commands download -these files to a GNU/Linux or similar host; see the downloaded +these files to a GNU/Linux or similar host; +see the downloaded README file for what to do next.

wget 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz'
 gzip -dc tzcode*.tar.gz | tar -xf -
@@ -92,7 +101,10 @@ mailing list, retrieve the archive of old
 messages (in gzip compressed format), or retrieve archived older versions of code
-and data.

+and data; there is also a smaller HTTP +mirror.

The Web has several other sources for time zone and daylight saving time data. Here are some recent links that may be of interest. @@ -104,14 +116,11 @@ is a text-based point-and-click interface to tables of current time throughout the world.

  • Fancier web interfaces, roughly in ascending order of complexity, include:
  • -
  • The Worldwide Holiday -& Festival Site lists DST-related clock changes along with -holidays.
  • The World Clock - Time Zones is a web interface to a time zone database derived from @@ -121,21 +130,29 @@ is a web interface to a time zone database derived from

    Other tz compilers

    @@ -144,51 +161,63 @@ definition that corresponded to iCalendar.
  • Timezone Converter describes a program Vzic that compiles tz source into iCalendar-compatible VTIMEZONE files. Vzic is freely -available under the GNU -General Public License (GPL). +available under the GNU +General Public License (GPL).
  • DateTime::TimeZone contains a script parse_olson that compiles tz source into Perl modules. It is part of the Perl DateTime Project, which is freely -available under both the GPL and the Perl Artistic -License. DateTime::TimeZone also contains a script +available under both the GPL and the Perl Artistic +License. DateTime::TimeZone also contains a script tests_from_zdump that generates test cases for each clock transition in the tz database.
  • -
  • International Components for -Unicode (ICU) contains a C/C++ library for internationalization that -has a compiler from tz source into an ICU-specific format. -ICU is freely available under a BSD-style license.
  • +
  • ICU +contains a C/C++ library for internationalization that +has a compiler from tz source +into an ICU-specific format. +ICU is freely available under a +BSD-style license.
  • Joda Time - Java date -and time API contains a class +and time API +contains a class org.joda.time.tz.ZoneInfoCompiler that compiles tz source into a Joda-specific binary format. Joda Time -is freely available under a BSD-style license.
  • +is freely available under a BSD-style license. +
  • PyTZ - Python Time +Zone Library compiles tz source into +Python. +It is freely available under a BSD-style license.
  • Other tz binary file readers

      -
    • The GNU C Library +
    • The GNU C +Library has an independent, thread-safe implementation of a tz binary file reader. This library is freely available under the -GNU Lesser General Public License (LGPL), -and is widely used in GNU/Linux systems.
    • +GNU Lesser General Public License +(LGPL), +and is widely used in GNU/Linux systems.
    • ZoneInfo.java is a tz binary file reader written in Java. -It is freely available under the GNU LGPL.
    • +It is freely available under the GNU +LGPL.
    • Python time zones -is a tz binary file reader written in Python. It is freely available -under a BSD-style license.
    • +is a tz binary file reader written in Python. +It is freely available under a BSD-style license.

    Other tz-based time zone conversion software

    • Sun Java releases since 1.4 -contain a copy of a recent tz database in a Java-specific -format.
    • +contain a copy of a subset of a recent tz database in a +Java-specific format.
    • HyperCard time zones calculator is a HyperCard stack.
    • @@ -198,11 +227,11 @@ Microsoft Windows program.

    Other time zone databases

    diff --git a/lib/libc/time/zdump.c b/lib/libc/time/zdump.c index baaec05b26a..df9669979a9 100644 --- a/lib/libc/time/zdump.c +++ b/lib/libc/time/zdump.c @@ -5,8 +5,8 @@ #if defined(LIBC_SCCS) && !defined(lint) && !defined(NOID) static char elsieid[] = "@(#)zdump.c 7.31"; -static char rcsid[] = "$OpenBSD: zdump.c,v 1.13 2004/04/01 11:37:02 jmc Exp $"; -#endif /* LIBC_SCCS and not lint */ +static char rcsid[] = "$OpenBSD: zdump.c,v 1.14 2004/10/18 22:33:43 millert Exp $"; +static char elsieid[] = "@(#)zdump.c 7.40"; /* ** This code has been made independent of the rest of the time @@ -15,7 +15,7 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.13 2004/04/01 11:37:02 jmc Exp $"; */ #include "stdio.h" /* for stdout, stderr, perror */ -#include "string.h" /* for strcpy */ +#include "string.h" /* for strlcpy */ #include "sys/types.h" /* for time_t */ #include "time.h" /* for struct tm */ #include "stdlib.h" /* for exit, malloc, atoi */ @@ -72,16 +72,15 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.13 2004/04/01 11:37:02 jmc Exp $"; #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) #endif /* !defined isleap */ -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #include "locale.h" /* for setlocale */ #include "libintl.h" -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ #ifndef GNUC_or_lint #ifdef lint #define GNUC_or_lint -#endif /* defined lint */ -#ifndef lint +#else /* !defined lint */ #ifdef __GNUC__ #define GNUC_or_lint #endif /* defined __GNUC__ */ @@ -91,8 +90,7 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.13 2004/04/01 11:37:02 jmc Exp $"; #ifndef INITIALIZE #ifdef GNUC_or_lint #define INITIALIZE(x) ((x) = 0) -#endif /* defined GNUC_or_lint */ -#ifndef GNUC_or_lint +#else /* !defined GNUC_or_lint */ #define INITIALIZE(x) #endif /* !defined GNUC_or_lint */ #endif /* !defined INITIALIZE */ @@ -104,11 +102,11 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.13 2004/04/01 11:37:02 jmc Exp $"; */ #ifndef _ -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT #define _(msgid) gettext(msgid) -#else /* !(HAVE_GETTEXT - 0) */ +#else /* !HAVE_GETTEXT */ #define _(msgid) msgid -#endif /* !(HAVE_GETTEXT - 0) */ +#endif /* !HAVE_GETTEXT */ #endif /* !defined _ */ #ifndef TZ_DOMAIN @@ -118,8 +116,7 @@ static char rcsid[] = "$OpenBSD: zdump.c,v 1.13 2004/04/01 11:37:02 jmc Exp $"; #ifndef P #ifdef __STDC__ #define P(x) x -#endif /* defined __STDC__ */ -#ifndef __STDC__ +#else /* !defined __STDC__ */ #define P(x) () #endif /* !defined __STDC__ */ #endif /* !defined P */ @@ -137,6 +134,7 @@ static time_t hunt P((char * name, time_t lot, time_t hit)); static size_t longest; static char * progname; static void show P((char * zone, time_t t, int v)); +static void dumptime P((const struct tm * tmp)); int main(argc, argv) @@ -158,13 +156,13 @@ char * argv[]; struct tm newtm; INITIALIZE(cuttime); -#if HAVE_GETTEXT - 0 +#if HAVE_GETTEXT (void) setlocale(LC_MESSAGES, ""); #ifdef TZ_DOMAINDIR (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR); -#endif /* defined(TEXTDOMAINDIR) */ +#endif /* defined TEXTDOMAINDIR */ (void) textdomain(TZ_DOMAIN); -#endif /* HAVE_GETTEXT - 0 */ +#endif /* HAVE_GETTEXT */ progname = argv[0]; vflag = 0; cutoff = NULL; @@ -326,7 +324,7 @@ struct tm * oldp; return -delta(oldp, newp); result = 0; for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy) - result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE); + result += DAYSPERNYEAR + isleap(tmy + (long) TM_YEAR_BASE); result += newp->tm_yday - oldp->tm_yday; result *= HOURSPERDAY; result += newp->tm_hour - oldp->tm_hour; @@ -346,10 +344,12 @@ int v; struct tm * tmp; (void) printf("%-*s ", (int) longest, zone); - if (v) - (void) printf("%.24s UTC = ", asctime(gmtime(&t))); + if (v) { + dumptime(gmtime(&t)); + (void) printf(" UTC = "); + } tmp = localtime(&t); - (void) printf("%.24s", asctime(tmp)); + dumptime(tmp); if (*abbr(tmp) != '\0') (void) printf(" %s", abbr(tmp)); if (v) { @@ -373,3 +373,37 @@ struct tm * tmp; result = tzname[tmp->tm_isdst]; return (result == NULL) ? &nada : result; } + +static void +dumptime(timeptr) +register const struct tm * timeptr; +{ + static const char wday_name[][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char mon_name[][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + register const char * wn; + register const char * mn; + + /* + ** The packaged versions of localtime and gmtime never put out-of-range + ** values in tm_wday or tm_mon, but since this code might be compiled + ** with other (perhaps experimental) versions, paranoia is in order. + */ + if (timeptr->tm_wday < 0 || timeptr->tm_wday >= + (int) (sizeof wday_name / sizeof wday_name[0])) + wn = "???"; + else wn = wday_name[timeptr->tm_wday]; + if (timeptr->tm_mon < 0 || timeptr->tm_mon >= + (int) (sizeof mon_name / sizeof mon_name[0])) + mn = "???"; + else mn = mon_name[timeptr->tm_mon]; + (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d %ld", + wn, mn, + timeptr->tm_mday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, + timeptr->tm_year + (long) TM_YEAR_BASE); +} -- cgit v1.2.3