?? timezone.c
字號:
/* Copyright (c) 1990-2001 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html*//* Replacement time library functions, based on platform independent public * domain timezone code from ftp://elsie.nci.nih.gov/pub, with mktime and * mkgmtime from our own mktime.c in Zip. * * Contains: tzset() * __tzset() * gmtime() * localtime() * mktime() * mkgmtime() * GetPlatformLocalTimezone() [different versions] *//* HISTORY/CHANGES * 17 Jun 00, Paul Kienitz, added the PD-based tzset(), localtime(), and so on * to amiga/filedate.c, replacing GNU-based functions which had * replaced time_lib.c, both having been rejected for licensing * reasons. Support for timezone files and leap seconds was removed. * * 23 Aug 00, Paul Kienitz, split into separate timezone.c file, made platform * independent, copied in mktime() and mkgmtime() from Zip, renamed * locale_TZ as GetPlatformLocalTimezone(), for use as a generic * hook by other platforms. */#ifndef __timezone_c#define __timezone_c#include "zip.h"#include "timezone.h"#include <ctype.h>#include <errno.h>#ifdef IZTZ_DEFINESTDGLOBALSlong timezone = 0;int daylight = 0;char *tzname[2];#endif#ifndef IZTZ_GETLOCALETZINFO# define IZTZ_GETLOCALETZINFO(ptzstruct, pgenrulefunct) (FALSE)#endifint real_timezone_is_set = FALSE; /* set by tzset() */#define TZDEFRULESTRING ",M4.1.0,M10.5.0"#define TZDEFAULT "EST5EDT"#define SECSPERMIN 60#define MINSPERHOUR 60#define HOURSPERDAY 24#define DAYSPERWEEK 7#define DAYSPERNYEAR 365#define DAYSPERLYEAR 366#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)#define MONSPERYEAR 12#define EPOCH_WDAY 4 /* Jan 1, 1970 was thursday */#define EPOCH_YEAR 1970#define TM_YEAR_BASE 1900#define FIRST_GOOD_YEAR ((time_t) -1 < (time_t) 1 ? EPOCH_YEAR-68 : EPOCH_YEAR)#define LAST_GOOD_YEAR (EPOCH_YEAR + ((time_t) -1 < (time_t) 1 ? 67 : 135))#define YDAYS(month, year) yr_days[leap(year)][month]/* Nonzero if `y' is a leap year, else zero. */#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)/* Number of leap years from EPOCH_YEAR to `y' (not including `y' itself). */#define _P4 ((EPOCH_YEAR / 4) * 4 + 1)#define _P100 ((EPOCH_YEAR / 100) * 100 + 1)#define _P400 ((EPOCH_YEAR / 400) * 400 + 1)#define nleap(y) (((y) - _P4) / 4 - ((y) - _P100) / 100 + ((y) - _P400) / 400)/* Length of month `m' (0 .. 11) */#define monthlen(m, y) (yr_days[0][(m)+1] - yr_days[0][m] + \ ((m) == 1 && leap(y)))/* internal module-level constants */#ifndef IZ_MKTIME_ONLYstatic ZCONST char gmt[] = "GMT";static ZCONST int mon_lengths[2][MONSPERYEAR] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }};#endif /* !IZ_MKTIME_ONLY */static ZCONST int yr_days[2][MONSPERYEAR+1] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }};#ifndef IZ_MKTIME_ONLYstatic ZCONST int year_lengths[2] = { DAYSPERNYEAR, DAYSPERLYEAR};/* internal variables */static struct state statism;/* prototypes of static functions */static time_t transtime OF((ZCONST time_t janfirst, ZCONST int year, ZCONST struct rule * ZCONST rulep, ZCONST long offset));static void generate_transitions OF((register struct state * ZCONST sp, ZCONST struct rule * ZCONST start, ZCONST struct rule * ZCONST end));static ZCONST char *getzname OF((ZCONST char *strp));static ZCONST char *getnum OF((ZCONST char *strp, int * ZCONST nump, ZCONST int min, ZCONST int max));static ZCONST char *getsecs OF((ZCONST char *strp, long * ZCONST secsp));static ZCONST char *getoffset OF((ZCONST char *strp, long * ZCONST offsetp));static ZCONST char *getrule OF((ZCONST char *strp, struct rule * ZCONST rulep));static int Parse_TZ OF((ZCONST char *name, register struct state * ZCONST sp));static time_t transtime(janfirst, year, rulep, offset) ZCONST time_t janfirst; ZCONST int year; ZCONST struct rule * ZCONST rulep; ZCONST long offset;{ register int leapyear; register time_t value; register int i; int d, m1, yy0, yy1, yy2, dow; value = 0; leapyear = leap(year); switch (rulep->r_type) { case JULIAN_DAY: /* ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap ** years. ** In non-leap years, or if the day number is 59 or less, just ** add SECSPERDAY times the day number-1 to the time of ** January 1, midnight, to get the day. */ value = janfirst + (rulep->r_day - 1) * SECSPERDAY; if (leapyear && rulep->r_day >= 60) value += SECSPERDAY; break; case DAY_OF_YEAR: /* ** n - day of year. ** Just add SECSPERDAY times the day number to the time of ** January 1, midnight, to get the day. */ value = janfirst + rulep->r_day * SECSPERDAY; break; case MONTH_NTH_DAY_OF_WEEK: /* ** Mm.n.d - nth "dth day" of month m. */ value = janfirst;/* for (i = 0; i < rulep->r_mon - 1; ++i) value += mon_lengths[leapyear][i] * SECSPERDAY;*/ value += yr_days[leapyear][rulep->r_mon - 1] * SECSPERDAY; /* ** Use Zeller's Congruence to get day-of-week of first day of ** month. */ m1 = (rulep->r_mon + 9) % 12 + 1; yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; yy1 = yy0 / 100; yy2 = yy0 % 100; dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; if (dow < 0) dow += DAYSPERWEEK; /* ** "dow" is the day-of-week of the first day of the month. Get ** the day-of-month (zero-origin) of the first "dow" day of the ** month. */ d = rulep->r_day - dow; if (d < 0) d += DAYSPERWEEK; for (i = 1; i < rulep->r_week; ++i) { if (d + DAYSPERWEEK >= mon_lengths[leapyear][rulep->r_mon - 1]) break; d += DAYSPERWEEK; } /* ** "d" is the day-of-month (zero-origin) of the day we want. */ value += d * SECSPERDAY; break; } /* ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in ** question. To get the Epoch-relative time of the specified local ** time on that day, add the transition time and the current offset ** from UTC. */ return value + rulep->r_time + offset;}static void generate_transitions(sp, start, end) register struct state * ZCONST sp; ZCONST struct rule * ZCONST start; ZCONST struct rule * ZCONST end;{ register int year; register time_t janfirst; time_t starttime; time_t endtime; long stdoffset = -sp->ttis[0].tt_gmtoff; long dstoffset = -sp->ttis[1].tt_gmtoff; register time_t * atp; register unsigned char * typep; /* ** Two transitions per year, from EPOCH_YEAR to LAST_GOOD_YEAR. */ sp->timecnt = 2 * (LAST_GOOD_YEAR - EPOCH_YEAR + 1); atp = sp->ats; typep = sp->types; janfirst = 0; for (year = EPOCH_YEAR; year <= LAST_GOOD_YEAR; ++year) { starttime = transtime(janfirst, year, start, stdoffset); endtime = transtime(janfirst, year, end, dstoffset); if (starttime > endtime) { *atp++ = endtime; *typep++ = 0; /* DST ends */ *atp++ = starttime; *typep++ = 1; /* DST begins */ } else { *atp++ = starttime; *typep++ = 1; /* DST begins */ *atp++ = endtime; *typep++ = 0; /* DST ends */ } janfirst += year_lengths[leap(year)] * SECSPERDAY; }}static ZCONST char *getzname(strp) ZCONST char *strp;{ register char c; while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' && c != '+') ++strp; return strp;}static ZCONST char *getnum(strp, nump, min, max) ZCONST char *strp; int * ZCONST nump; ZCONST int min; ZCONST int max;{ register char c; register int num; if (strp == NULL || !isdigit(c = *strp)) return NULL; num = 0; do { num = num * 10 + (c - '0'); if (num > max) return NULL; /* illegal value */ c = *++strp; } while (isdigit(c)); if (num < min) return NULL; /* illegal value */ *nump = num; return strp;}static ZCONST char *getsecs(strp, secsp) ZCONST char *strp; long * ZCONST secsp;{ int num; /* ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like ** "M10.4.6/26", which does not conform to Posix, ** but which specifies the equivalent of ** ``02:00 on the first Sunday on or after 23 Oct''. */ strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); if (strp == NULL) return NULL; *secsp = num * (long) SECSPERHOUR; if (*strp == ':') { ++strp; strp = getnum(strp, &num, 0, MINSPERHOUR - 1); if (strp == NULL) return NULL; *secsp += num * SECSPERMIN; if (*strp == ':') { ++strp; /* `SECSPERMIN' allows for leap seconds. */ strp = getnum(strp, &num, 0, SECSPERMIN); if (strp == NULL) return NULL; *secsp += num; } } return strp;}static ZCONST char *getoffset(strp, offsetp) ZCONST char *strp; long * ZCONST offsetp;{ register int neg = 0; if (*strp == '-') { neg = 1; ++strp; } else if (*strp == '+') ++strp; strp = getsecs(strp, offsetp); if (strp == NULL) return NULL; /* illegal time */ if (neg) *offsetp = -*offsetp; return strp;}static ZCONST char *getrule(strp, rulep) ZCONST char *strp; struct rule * ZCONST rulep;{ if (*strp == 'J') { /* ** Julian day. */ rulep->r_type = JULIAN_DAY; ++strp; strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); } else if (*strp == 'M') { /* ** Month, week, day. */ rulep->r_type = MONTH_NTH_DAY_OF_WEEK; ++strp; strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_week, 1, 5); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); } else if (isdigit(*strp)) { /* ** Day of year. */ rulep->r_type = DAY_OF_YEAR; strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); } else return NULL; /* invalid format */ if (strp == NULL) return NULL; if (*strp == '/') { /* ** Time specified. */ ++strp; strp = getsecs(strp, &rulep->r_time); } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ return strp;}static int Parse_TZ(name, sp) ZCONST char *name; register struct state * ZCONST sp;{ ZCONST char * stdname; ZCONST char * dstname; size_t stdlen; size_t dstlen; long stdoffset; long dstoffset; register char * cp; dstname = NULL; stdname = name; name = getzname(name);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -