revised proposed time zone abbreviation changes
Arthur David Olson
olsona at lecserver.nci.nih.gov
Mon Jun 6 15:22:42 UTC 2005
Thanks to folks for feedback on time zone abbreviation changes.
Below find revised changes reflecting the feedback.
The changes are relative to what's now available in the ftp directory.
The revisions:
1. the set of characters allowed in time zone abbreviations has been
expanded to include '.' (as in "E.S.T.") and '_'
(on general principles).
2. the character substituted for those outside the approved set has been
changed to '_' (a character which does not appear in any of the
abbreviations that currently appear in the time zone data files).
Regarding abbreviation lengths: I agree that some folks might want to use
abbreviations shorter than three letters (in particular the old-style
single-letter names for zones), so localtime.c is set up to allow fewer than
three. It also allows up to 16 (covering abbreviations such as
"XSTDST+hh:mm:ss" that Sun accepts). However, since the data files generated
by zic might end up being used on systems with stricter requirements, it seems
prudent to issue warnings (note: not errors) regarding short and long
abbreviations.
--ado
diff -r -c old/Makefile new/Makefile
*** old/Makefile Mon Apr 4 11:24:31 2005
--- new/Makefile Thu May 26 12:42:13 2005
***************
*** 1,4 ****
! # @(#)Makefile 7.108
# Change the line below for your time zone (after finding the zone you want in
# the time zone files, or adding it to a time zone file).
--- 1,4 ----
! # @(#)Makefile 7.109
# Change the line below for your time zone (after finding the zone you want in
# the time zone files, or adding it to a time zone file).
***************
*** 111,117 ****
# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
# if you do not want run time warnings about formats that may cause
# year 2000 grief
! #
GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \
-Wall -Wcast-qual -Wconversion -Wmissing-prototypes \
-Wnested-externs -Wpointer-arith -Wshadow \
--- 111,119 ----
# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
# if you do not want run time warnings about formats that may cause
# year 2000 grief
! # -DZIC_MAX_ABBR_LEN_WO_WARN=3
! # (or some other number) to set the maximum time zone abbreviation length
! # that zic will accept without a warning (the default is 6)
GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \
-Wall -Wcast-qual -Wconversion -Wmissing-prototypes \
-Wnested-externs -Wpointer-arith -Wshadow \
diff -r -c old/localtime.c new/localtime.c
*** old/localtime.c Mon Apr 4 11:24:32 2005
--- new/localtime.c Mon Jun 6 11:12:54 2005
***************
*** 5,11 ****
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.91";
#endif /* !defined NOID */
#endif /* !defined lint */
--- 5,11 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)localtime.c 7.94";
#endif /* !defined NOID */
#endif /* !defined lint */
***************
*** 22,27 ****
--- 22,40 ----
#include "fcntl.h"
#include "float.h" /* for FLT_MAX and DBL_MAX */
+ #ifndef TZ_ABBR_MAX_LEN
+ #define TZ_ABBR_MAX_LEN 16
+ #endif /* !defined TZ_ABBR_MAX_LEN */
+
+ #ifndef TZ_ABBR_CHAR_SET
+ #define TZ_ABBR_CHAR_SET \
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+ #endif /* !defined TZ_ABBR_CHAR_SET */
+
+ #ifndef TZ_ABBR_ERR_CHAR
+ #define TZ_ABBR_ERR_CHAR '_'
+ #endif /* !defined TZ_ABBR_ERR_CHAR */
+
/*
** SunOS 4.1.1 headers lack O_BINARY.
*/
***************
*** 124,129 ****
--- 137,143 ----
static long detzcode P((const char * codep));
static const char * getzname P((const char * strp));
+ static const char * getqzname P((const char * strp, const char delim));
static const char * getnum P((const char * strp, int * nump, int min,
int max));
static const char * getsecs P((const char * strp, long * secsp));
***************
*** 269,274 ****
--- 283,306 ----
tzname[ttisp->tt_isdst] =
&sp->chars[ttisp->tt_abbrind];
}
+ /*
+ ** Finally, scrub the abbreviations.
+ ** First, replace bogus characters.
+ */
+ for (i = 0; i < sp->charcnt; ++i)
+ if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
+ sp->chars[i] = TZ_ABBR_ERR_CHAR;
+ /*
+ ** Second, truncate long abbreviations.
+ */
+ for (i = 0; i < sp->typecnt; ++i) {
+ register const struct ttinfo * const ttisp = &sp->ttis[i];
+ register char * cp = &sp->chars[ttisp->tt_abbrind];
+
+ if (strlen(cp) > TZ_ABBR_MAX_LEN &&
+ strcmp(cp, GRANDPARENTED) != 0)
+ *(cp + TZ_ABBR_MAX_LEN) = '\0';
+ }
}
static int
***************
*** 470,475 ****
--- 502,528 ----
}
/*
+ ** Given a pointer into an extended time zone string, scan until the ending
+ ** delimiter of the zone name is located. Return a pointer to the delimiter.
+ **
+ ** As with getzname above, the legal character set is actually quite
+ ** restricted, with other characters producing undefined results.
+ ** We choose not to care - allowing almost anything to be in the zone abbrev.
+ */
+
+ static const char *
+ getqzname(strp, delim)
+ register const char * strp;
+ const char delim;
+ {
+ register char c;
+
+ while ((c = *strp) != '\0' && c != delim)
+ ++strp;
+ return strp;
+ }
+
+ /*
** Given a pointer into a time zone string, extract a number from that string.
** Check that the number is within a specified range; if it is not, return
** NULL.
***************
*** 753,760 ****
stdlen = (sizeof sp->chars) - 1;
stdoffset = 0;
} else {
! name = getzname(name);
! stdlen = name - stdname;
if (stdlen < 3)
return -1;
if (*name == '\0')
--- 806,823 ----
stdlen = (sizeof sp->chars) - 1;
stdoffset = 0;
} else {
! if (*name == '<') {
! name++;
! stdname = name;
! name = getqzname(name, '>');
! if (*name != '>')
! return (-1);
! stdlen = name - stdname;
! name++;
! } else {
! name = getzname(name);
! stdlen = name - stdname;
! }
if (stdlen < 3)
return -1;
if (*name == '\0')
***************
*** 767,775 ****
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
! dstname = name;
! name = getzname(name);
! dstlen = name - dstname; /* length of DST zone name */
if (dstlen < 3)
return -1;
if (*name != '\0' && *name != ',' && *name != ';') {
--- 830,847 ----
if (load_result != 0)
sp->leapcnt = 0; /* so, we're off a little */
if (*name != '\0') {
! if (*name == '<') {
! dstname = ++name;
! name = getqzname(name, '>');
! if (*name != '>')
! return -1;
! dstlen = name - dstname;
! name++;
! } else {
! dstname = name;
! name = getzname(name);
! dstlen = name - dstname; /* length of DST zone name */
! }
if (dstlen < 3)
return -1;
if (*name != '\0' && *name != ',' && *name != ';') {
diff -r -c old/private.h new/private.h
*** old/private.h Mon Apr 4 11:24:32 2005
--- new/private.h Thu May 26 14:54:07 2005
***************
*** 25,30 ****
--- 25,32 ----
#endif /* !defined NOID */
#endif /* !defined lint */
+ #define GRANDPARENTED "Local time zone must be set--see zic manual page"
+
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
diff -r -c old/solar87 new/solar87
*** old/solar87 Thu Apr 21 15:04:16 2005
--- new/solar87 Thu May 26 12:42:35 2005
***************
*** 1,4 ****
! # @(#)solar87 7.3
# So much for footnotes about Saudi Arabia.
# Apparent noon times below are for Riyadh; your mileage will vary.
--- 1,4 ----
! # @(#)solar87 7.4
# So much for footnotes about Saudi Arabia.
# Apparent noon times below are for Riyadh; your mileage will vary.
***************
*** 381,388 ****
# Before and after 1987, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh87 3:07:04 - ?? 1987
! 3:07:04 sol87 ?? 1988
! 3:07:04 - ??
# For backward compatibility...
Link Asia/Riyadh87 Mideast/Riyadh87
--- 381,388 ----
# Before and after 1987, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh87 3:07:04 - zzz 1987
! 3:07:04 sol87 zzz 1988
! 3:07:04 - zzz
# For backward compatibility...
Link Asia/Riyadh87 Mideast/Riyadh87
diff -r -c old/solar88 new/solar88
*** old/solar88 Thu Apr 21 15:04:16 2005
--- new/solar88 Thu May 26 12:42:35 2005
***************
*** 1,4 ****
! # @(#)solar88 7.3
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using formulas in the U.S. Naval Observatory's
--- 1,4 ----
! # @(#)solar88 7.4
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using formulas in the U.S. Naval Observatory's
***************
*** 381,388 ****
# Before and after 1988, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh88 3:07:04 - ?? 1988
! 3:07:04 sol88 ?? 1989
! 3:07:04 - ??
# For backward compatibility...
Link Asia/Riyadh88 Mideast/Riyadh88
--- 381,388 ----
# Before and after 1988, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh88 3:07:04 - zzz 1988
! 3:07:04 sol88 zzz 1989
! 3:07:04 - zzz
# For backward compatibility...
Link Asia/Riyadh88 Mideast/Riyadh88
diff -r -c old/solar89 new/solar89
*** old/solar89 Thu Apr 21 15:04:16 2005
--- new/solar89 Thu May 26 12:42:35 2005
***************
*** 1,4 ****
! # @(#)solar89 7.4
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using a formula provided by the U. S. Naval Observatory:
--- 1,4 ----
! # @(#)solar89 7.5
# Apparent noon times below are for Riyadh; they're a bit off for other places.
# Times were computed using a formula provided by the U. S. Naval Observatory:
***************
*** 386,393 ****
# Before and after 1989, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh89 3:07:04 - ?? 1989
! 3:07:04 sol89 ?? 1990
! 3:07:04 - ??
# For backward compatibility...
Link Asia/Riyadh89 Mideast/Riyadh89
--- 386,393 ----
# Before and after 1989, we'll operate on local mean solar time.
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
! Zone Asia/Riyadh89 3:07:04 - zzz 1989
! 3:07:04 sol89 zzz 1990
! 3:07:04 - zzz
# For backward compatibility...
Link Asia/Riyadh89 Mideast/Riyadh89
diff -r -c old/zdump.c new/zdump.c
*** old/zdump.c Mon Apr 4 11:24:32 2005
--- new/zdump.c Thu May 26 12:48:56 2005
***************
*** 1,4 ****
! static char elsieid[] = "@(#)zdump.c 7.64";
/*
** This code has been made independent of the rest of the time
--- 1,4 ----
! static char elsieid[] = "@(#)zdump.c 7.65";
/*
** This code has been made independent of the rest of the time
***************
*** 144,151 ****
--- 144,153 ----
static time_t absolute_max_time;
static size_t longest;
static char * progname;
+ static int warned;
static char * abbr P((struct tm * tmp));
+ static void abbrok P((const char * abbr, const char * zone));
static long delta P((struct tm * newp, struct tm * oldp));
static void dumptime P((const struct tm * tmp));
static time_t hunt P((char * name, time_t lot, time_t hit));
***************
*** 191,196 ****
--- 193,236 ----
}
#endif /* !defined TYPECHECK */
+ static void
+ abbrok(abbr, zone)
+ const char * const abbr;
+ const char * const zone;
+ {
+ register int i;
+ register const char * cp;
+ register char * wp;
+
+ if (warned)
+ return;
+ cp = abbr;
+ wp = NULL;
+ while (isascii(*cp) && isalpha(*cp))
+ ++cp;
+ if (cp - abbr == 0)
+ wp = _("lacks alphabetic at start");
+ if (cp - abbr < 3)
+ wp = _("has fewer than 3 alphabetics");
+ if (cp - abbr > 6)
+ wp = _("has more than 6 alphabetics");
+ if (wp == NULL && (*cp == '+' || *cp == '-')) {
+ ++cp;
+ if (isascii(*cp) && isdigit(*cp))
+ if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
+ ++cp;
+ }
+ if (*cp != '\0')
+ wp = _("differs from POSIX standard");
+ if (wp == NULL)
+ return;
+ (void) fflush(stdout);
+ (void) fprintf(stderr,
+ "%s: warning: zone \"%s\" abbreviation \"%s\" %s\n",
+ progname, zone, abbr, wp);
+ warned = TRUE;
+ }
+
int
main(argc, argv)
int argc;
***************
*** 297,302 ****
--- 337,343 ----
show(argv[i], now, FALSE);
continue;
}
+ warned = FALSE;
t = absolute_min_time;
show(argv[i], t, TRUE);
t += SECSPERHOUR * HOURSPERDAY;
***************
*** 527,532 ****
--- 568,575 ----
}
}
(void) printf("\n");
+ if (tmp != NULL && *abbr(tmp) != '\0')
+ abbrok(abbr(tmp), zone);
}
static char *
diff -r -c old/zic.c new/zic.c
*** old/zic.c Mon Apr 4 11:24:32 2005
--- new/zic.c Thu May 26 14:54:07 2005
***************
*** 1,4 ****
! static char elsieid[] = "@(#)zic.c 7.122";
/*
** Regardless of the type of time_t, we do our work using this type.
--- 1,4 ----
! static char elsieid[] = "@(#)zic.c 7.124";
/*
** Regardless of the type of time_t, we do our work using this type.
***************
*** 10,15 ****
--- 10,19 ----
#include "locale.h"
#include "tzfile.h"
+ #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
+ #define ZIC_MAX_ABBR_LEN_WO_WARN 6
+ #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
+
#if HAVE_SYS_STAT_H
#include "sys/stat.h"
#endif
***************
*** 2196,2201 ****
--- 2200,2240 ----
{
register int i;
+ if (strcmp(string, GRANDPARENTED) != 0) {
+ register const char * cp;
+ register char * wp;
+
+ /*
+ ** Want one to ZIC_MAX_ABBR_LEN_WO_WARN alphabetics
+ ** optionally followed by a + or - and a number from 1 to 14.
+ */
+ cp = string;
+ wp = NULL;
+ while (isascii(*cp) && isalpha(*cp))
+ ++cp;
+ if (cp - string == 0)
+ wp = _("time zone abbreviation lacks alphabetic at start");
+ if (noise && cp - string > 3)
+ wp = _("time zone abbreviation has more than 3 alphabetics");
+ if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
+ wp = _("time zone abbreviation has too many alphabetics");
+ if (wp == NULL && (*cp == '+' || *cp == '-')) {
+ ++cp;
+ if (isascii(*cp) && isdigit(*cp))
+ if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
+ ++cp;
+ }
+ if (*cp != '\0')
+ wp = _("time zone abbreviation differs from POSIX standard");
+ if (wp != NULL) {
+ wp = ecpyalloc(wp);
+ wp = ecatalloc(wp, " (");
+ wp = ecatalloc(wp, string);
+ wp = ecatalloc(wp, ")");
+ warning(wp);
+ ifree(wp);
+ }
+ }
i = strlen(string) + 1;
if (charcnt + i > TZ_MAX_CHARS) {
error(_("too many, or too long, time zone abbreviations"));
More information about the tz
mailing list