4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Time Zone processing.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials are licensed and made available under
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the terms and conditions of the BSD License that accompanies this distribution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Portions derived from the NIH time zone package file, localtime.c,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which contains the following notice:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This file is in the public domain, so clarified as of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetBSD: localtime.c,v 1.39 2006/03/22 14:01:30 christos Exp
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Someone might make incorrect use of a time zone abbreviation:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 1. They might reference tzname[0] before calling tzset (explicitly
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** or implicitly).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 2. They might reference tzname[1] before calling tzset (explicitly
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** or implicitly).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 3. They might reference tzname[1] after setting to a time zone
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** in which Daylight Saving Time is never observed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 4. They might reference tzname[0] after setting to a time zone
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** in which Standard Time is never observed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** 5. They might reference tm.TM_ZONE after calling offtime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** What's best to do in the above cases is open to debate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** for now, we just set things up so that in any of the five cases
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** WILDABBR is used. Another possibility: initialize tzname[0] to the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** string "tzname[0] used before set", and similarly for the other cases.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** And another: initialize tzname[0] to "ERA", with an explanation in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** manual page of what this "time zone abbreviation" means (doing this so
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** that tzname[0] has the "normal" length of three characters).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* !defined WILDABBR */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* !defined TZ_STRLEN_MAX */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//static int gmt_is_set = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Get first 4 characters of codep as a 32-bit integer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The first character of codep becomes the MSB of the resultant integer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** The first character must be sign extended on systems with >32bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** longs. This was solved differently in the master tzcode sources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** (the fix first appeared in tzcode95c.tar.gz). But I believe
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** that this implementation is superior.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif /* NO_ZONEINFO_FILES */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const struct ttinfo * const ttisp = &sp->ttis[i];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** And to get the latest zone names into tzname. . .
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, scan until a character that is not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** a valid character in a zone name is found. Return a pointer to that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** character.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register char c;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract a number from that string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Check that the number is within a specified range; if it is not, return
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int * const nump,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register char c;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (is_digit(c));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract a number of seconds,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** in hh[:mm[:ss]] form, from the string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** If any error occurs, return NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** of seconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "M10.4.6/26", which does not conform to Posix,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** but which specifies the equivalent of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** ``02:00 on the first Sunday on or after 23 Oct''.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* `SECSPERMIN' allows for leap seconds. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract an offset, in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** [+-]hh[:mm[:ss]] form, from the string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** If any error occurs, return NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a pointer into a time zone string, extract a rule in the form
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** date[/time]. See POSIX section 8 for the format of "date" and "time".
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** If a valid rule is not found, return NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Otherwise, return a pointer to the first character not part of the rule.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *strp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Julian day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Month, week, day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Day of year.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Time specified.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctzload(register const char *name, register struct state * const sp)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register const char * p;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Section 4.9.1 of the C standard says that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "FILENAME_MAX expands to an integral constant expression
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** that is the size needed for an array of char large enough
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** to hold the longest file name string that the implementation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** guarantees can be opened."
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strcpy(fullname, p); /* XXX strcpy is safe */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strcat(fullname, "/"); /* XXX strcat is safe */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void) strcat(fullname, name); /* XXX strcat is safe */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Set doaccess if '.' (as in "../") shows up in name.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * XXX potential security problem here if user of a set-id
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * program has set TZ (which is passed in as name) here,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and uses a race condition trick to defeat the access(2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else /* ! NO_ZONEINFO_FILES */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** year, a rule, and the offset from UTC at the time that rule takes effect,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** calculate the Epoch-relative time that rule takes effect.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** In non-leap years, or if the day number is 59 or less, just
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** add SECSPERDAY times the day number-1 to the time of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** January 1, midnight, to get the day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** n - day of year.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Just add SECSPERDAY times the day number to the time of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** January 1, midnight, to get the day.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Mm.n.d - nth "dth day" of month m.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Use Zeller's Congruence to get day-of-week of first day of
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "dow" is the day-of-week of the first day of the month. Get
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** the day-of-month (zero-origin) of the first "dow" day of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "d" is the day-of-month (zero-origin) of the day we want.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** question. To get the Epoch-relative time of the specified local
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** time on that day, add the transition time and the current offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** from UTC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Given a POSIX section 8-style TZ string, fill in the rule tables as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** appropriate.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char * name,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync stdlen = strlen(name); /* length of standard zone name */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dstlen = name - dstname; /* length of DST zone name */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*name != '\0' && *name != ',' && *name != ';') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Two transitions per year, from EPOCH_YEAR to 2037.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int i;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync register int j;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Initial values of theirstdoffset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Initially we're assumed to be in standard time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Now juggle transition times and types
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** tracking offsets as you do.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sp->types[i] = (unsigned char)sp->ttis[j].tt_isdst;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* No adjustment to transition time */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** If summer time is in effect, and the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** transition time was not specified as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** standard time, add the summer time
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** offset to the transition time;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** otherwise, add the standard time
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** offset to the transition time.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Transitions from DST to DDST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** will effectively disappear since
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** POSIX provides for only one DST
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** Finally, fill in ttis.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** ttisstd and ttisgmt need not be handled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void)strncpyX(lcl_TZname, name, sizeof(lcl_TZname));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ** User wants it fast rather than right.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (void)strncpyX(lclptr->chars, gmt, sizeof(lclptr->chars));