#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | lsinfo |
leap second information More... | |
struct | rule |
struct | state |
Defines | |
#define | BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) |
#define | DAY_OF_YEAR 1 |
#define | JULIAN_DAY 0 |
#define | MONTH_NTH_DAY_OF_WEEK 2 |
#define | MY_TZNAME_MAX 255 |
#define | OPEN_MODE O_RDONLY |
#define | TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
#define | TZ_ABBR_ERR_CHAR '_' |
#define | TZ_ABBR_MAX_LEN 16 |
#define | TZ_STRLEN_MAX 255 |
#define | TZDEFRULESTRING ",M4.1.0,M10.5.0" |
#define | WRONG (-1) |
Functions | |
static char | __attribute__ ((unused)) |
time type information | |
static | AST_LIST_HEAD_STATIC (zonelist, state) |
struct tm * | ast_localtime (const time_t *timep, struct tm *tmp, const char *zone) |
time_t | ast_mktime (struct tm *tmp, const char *zone) |
static struct state * | ast_tzset (const char *zone) |
static long | detzcode (const char *const codep) |
static time_t | detzcode64 (const char *const codep) |
static int | differ_by_repeat (const time_t t1, const time_t t0) |
static const char * | getnum (const char *strp, int *nump, const int min, const int max) |
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. Otherwise, return a pointer to the first character not part of the number. | |
static const char * | getoffset (const char *strp, long *offsetp) |
Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time. | |
static const char * | getqzname (const char *strp, const int delim) |
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. | |
static const char * | getrule (const char *strp, struct rule *rulep) |
Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule. | |
static const char * | getsecs (const char *strp, long *const secsp) |
Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds. | |
static const char * | getzname (const char *strp) |
Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character. | |
static int | gmtload (struct state *sp) |
static struct tm * | gmtsub (const time_t *timep, const long offset, struct tm *tmp) |
static int | increment_overflow (int *number, int delta) |
Simplified normalize logic courtesy Paul Eggert. | |
static int | leaps_thru_end_of (const int y) |
Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero. | |
static struct tm * | localsub (const time_t *timep, const long offset, struct tm *tmp, const struct state *sp) |
static int | long_increment_overflow (long *number, int delta) |
static int | long_normalize_overflow (long *tensptr, int *unitsptr, const int base) |
static int | normalize_overflow (int *tensptr, int *unitsptr, const int base) |
static int tzparse | P ((const char *name, struct state *sp, int lastditch)) |
static int tzload | P ((const char *name, struct state *sp, int doextend)) |
static time_t transtime | P ((time_t janfirst, int year, const struct rule *rulep, long offset)) |
static int tmcomp | P ((const struct tm *atmp, const struct tm *btmp)) |
static struct tm *timesub | P ((const time_t *timep, long offset, const struct state *sp, struct tm *tmp)) |
static time_t time2sub | P ((struct tm *tmp, struct tm *(*funcp)(const time_t *, long, struct tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp)) |
static time_t time2 | P ((struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp)) |
static time_t time1 | P ((struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, const struct state *sp)) |
static int normalize_overflow | P ((int *tensptr, int *unitsptr, const int base)) |
static int long_normalize_overflow | P ((long *tensptr, int *unitsptr, const int base)) |
static int long_increment_overflow | P ((long *number, int delta)) |
static int leaps_thru_end_of | P ((int y)) |
static int increment_overflow | P ((int *number, int delta)) |
static struct tm *localsub | P ((const time_t *timep, long offset, struct tm *tmp, const struct state *sp)) |
static struct tm *gmtsub | P ((const time_t *timep, long offset, struct tm *tmp)) |
static int gmtload | P ((struct state *sp)) |
static const char *getrule | P ((const char *strp, struct rule *rulep)) |
static const char *getoffset | P ((const char *strp, long *offsetp)) |
static const char *getsecs | P ((const char *strp, long *secsp)) |
static const char *getnum | P ((const char *strp, int *nump, int min, int max)) |
static const char *getqzname | P ((const char *strp, const int delim)) |
static const char *getzname | P ((const char *strp)) |
static int differ_by_repeat | P ((time_t t1, time_t t0)) |
static long detzcode | P ((const char *codep)) |
static time_t | time1 (struct tm *tmp, struct tm *(*const funcp)(const time_t *, long, struct tm *, const struct state *), const long offset, const struct state *sp) |
static time_t | time2 (struct tm *tmp, struct tm *(*const funcp)(const time_t *, long, struct tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp) |
static time_t | time2sub (struct tm *tmp, struct tm *(*const funcp)(const time_t *, long, struct tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp) |
static struct tm * | timesub (const time_t *timep, const long offset, const struct state *sp, struct tm *tmp) |
static int | tmcomp (const struct tm *atmp, const struct tm *btmp) |
static time_t | transtime (const time_t janfirst, const int year, const struct rule *rulep, const long offset) |
Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect. | |
static int | tzload (const char *name, struct state *const sp, const int doextend) |
static int | tzparse (const char *name, struct state *sp, const int lastditch) |
Variables | |
static const int | mon_lengths [2][MONSPERYEAR] |
static const int | year_lengths [2] |
The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/
Definition in file localtime.c.
#define BIGGEST | ( | a, | |||
b | ) | (((a) > (b)) ? (a) : (b)) |
Definition at line 130 of file localtime.c.
#define DAY_OF_YEAR 1 |
#define JULIAN_DAY 0 |
#define MONTH_NTH_DAY_OF_WEEK 2 |
#define MY_TZNAME_MAX 255 |
Definition at line 136 of file localtime.c.
#define OPEN_MODE O_RDONLY |
Referenced by tzload().
#define TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
#define TZ_ABBR_ERR_CHAR '_' |
#define TZ_ABBR_MAX_LEN 16 |
#define TZ_STRLEN_MAX 255 |
Definition at line 139 of file localtime.c.
#define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Referenced by tzparse().
#define WRONG (-1) |
Referenced by gmtload(), time1(), time2sub(), tzload(), and tzparse().
static char __attribute__ | ( | (unused) | ) | [static] |
time type information
Definition at line 70 of file localtime.c.
00080 :+-._" 00081 #endif /* !defined TZ_ABBR_CHAR_SET */ 00082 00083 #ifndef TZ_ABBR_ERR_CHAR 00084 #define TZ_ABBR_ERR_CHAR '_' 00085 #endif /* !defined TZ_ABBR_ERR_CHAR */ 00086 00087 /* 00088 ** SunOS 4.1.1 headers lack O_BINARY. 00089 */ 00090 00091 #ifdef O_BINARY 00092 #define OPEN_MODE (O_RDONLY | O_BINARY) 00093 #endif /* defined O_BINARY */ 00094 #ifndef O_BINARY 00095 #define OPEN_MODE O_RDONLY 00096 #endif /* !defined O_BINARY */ 00097 00098 static const char gmt[] = "GMT"; 00099 00100 /*! \note 00101 * The DST rules to use if TZ has no rules and we can't load TZDEFRULES. 00102 * We default to US rules as of 1999-08-17. 00103 * POSIX 1003.1 section 8.1.1 says that the default DST rules are 00104 * implementation dependent; for historical reasons, US rules are a 00105 * common default. 00106 */ 00107 #ifndef TZDEFRULESTRING 00108 #define TZDEFRULESTRING ",M4.1.0,M10.5.0" 00109 #endif /* !defined TZDEFDST */ 00110 00111 #ifndef WRONG 00112 #define WRONG (-1) 00113 #endif /* !defined WRONG */ 00114 00115 /*!< \brief time type information */ 00116 struct ttinfo { /* time type information */ 00117 long tt_gmtoff; /* UTC offset in seconds */ 00118 int tt_isdst; /* used to set tm_isdst */ 00119 int tt_abbrind; /* abbreviation list index */ 00120 int tt_ttisstd; /* TRUE if transition is std time */ 00121 int tt_ttisgmt; /* TRUE if transition is UTC */ 00122 };
static AST_LIST_HEAD_STATIC | ( | zonelist | , | |
state | ||||
) | [static] |
struct tm* ast_localtime | ( | const time_t * | timep, | |
struct tm * | tmp, | |||
const char * | zone | |||
) | [read] |
Definition at line 1143 of file localtime.c.
References ast_tzset(), and localsub().
Referenced by acf_strftime(), append_date(), ast_check_timing(), ast_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_ge(), ast_say_date_gr(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_tw(), ast_say_datetime_de(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_ge(), ast_say_datetime_from_now_pt(), ast_say_datetime_ge(), ast_say_datetime_gr(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_tw(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_ge(), ast_say_time_gr(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_tw(), ast_verbose(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), get_date(), iax2_datetime(), main(), manager_log(), odbc_log(), pgsql_log(), phone_call(), play_message_datetime(), rpt_localtime(), say_date_generic(), sip_show_registry(), sqlite_log(), transmit_notify_request_with_callerid(), vmu_tm(), and write_metadata().
01144 { 01145 const struct state *sp = ast_tzset(zone); 01146 memset(tmp, 0, sizeof(*tmp)); 01147 return sp ? localsub(timep, 0L, tmp, sp) : NULL; 01148 }
time_t ast_mktime | ( | struct tm * | tmp, | |
const char * | zone | |||
) |
Definition at line 1641 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime().
01642 { 01643 const struct state *sp; 01644 if (!(sp = ast_tzset(zone))) 01645 return 0; 01646 return time1(tmp, localsub, 0L, sp); 01647 }
static struct state* ast_tzset | ( | const char * | zone | ) | [static, read] |
Definition at line 1017 of file localtime.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), FALSE, gmtload(), state::name, TRUE, tzload(), and tzparse().
Referenced by ast_localtime(), and ast_mktime().
01018 { 01019 struct state *sp; 01020 01021 if (ast_strlen_zero(zone)) 01022 zone = "/etc/localtime"; 01023 01024 AST_LIST_LOCK(&zonelist); 01025 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01026 if (!strcmp(sp->name, zone)) { 01027 AST_LIST_UNLOCK(&zonelist); 01028 return sp; 01029 } 01030 } 01031 AST_LIST_UNLOCK(&zonelist); 01032 01033 if (!(sp = ast_calloc(1, sizeof *sp))) 01034 return NULL; 01035 01036 if (tzload(zone, sp, TRUE) != 0) { 01037 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0) 01038 (void) gmtload(sp); 01039 } 01040 ast_copy_string(sp->name, zone, sizeof(sp->name)); 01041 AST_LIST_LOCK(&zonelist); 01042 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01043 AST_LIST_UNLOCK(&zonelist); 01044 return sp; 01045 }
static long detzcode | ( | const char *const | codep | ) | [static] |
Definition at line 235 of file localtime.c.
Referenced by tzload().
00236 { 00237 long result; 00238 int i; 00239 00240 result = (codep[0] & 0x80) ? ~0L : 0; 00241 for (i = 0; i < 4; ++i) 00242 result = (result << 8) | (codep[i] & 0xff); 00243 return result; 00244 }
static time_t detzcode64 | ( | const char *const | codep | ) | [static] |
Definition at line 246 of file localtime.c.
Referenced by tzload().
00247 { 00248 time_t result; 00249 int i; 00250 00251 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 00252 for (i = 0; i < 8; ++i) 00253 result = result * 256 + (codep[i] & 0xff); 00254 return result; 00255 }
static int differ_by_repeat | ( | const time_t | t1, | |
const time_t | t0 | |||
) | [static] |
Definition at line 257 of file localtime.c.
References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.
Referenced by tzload().
00258 { 00259 const long long at1 = t1, at0 = t0; 00260 if (TYPE_INTEGRAL(time_t) && 00261 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) 00262 return 0; 00263 return at1 - at0 == SECSPERREPEAT; 00264 }
static const char* getnum | ( | const char * | strp, | |
int * | nump, | |||
const int | min, | |||
const int | max | |||
) | [static] |
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. Otherwise, return a pointer to the first character not part of the number.
Definition at line 546 of file localtime.c.
References is_digit.
Referenced by getrule(), and getsecs().
00547 { 00548 char c; 00549 int num; 00550 00551 if (strp == NULL || !is_digit(c = *strp)) 00552 return NULL; 00553 num = 0; 00554 do { 00555 num = num * 10 + (c - '0'); 00556 if (num > max) 00557 return NULL; /* illegal value */ 00558 c = *++strp; 00559 } while (is_digit(c)); 00560 if (num < min) 00561 return NULL; /* illegal value */ 00562 *nump = num; 00563 return strp; 00564 }
static const char* getoffset | ( | const char * | strp, | |
long * | offsetp | |||
) | [static] |
Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.
Definition at line 613 of file localtime.c.
References getsecs().
Referenced by tzparse().
00614 { 00615 int neg = 0; 00616 00617 if (*strp == '-') { 00618 neg = 1; 00619 ++strp; 00620 } else if (*strp == '+') 00621 ++strp; 00622 strp = getsecs(strp, offsetp); 00623 if (strp == NULL) 00624 return NULL; /* illegal time */ 00625 if (neg) 00626 *offsetp = -*offsetp; 00627 return strp; 00628 }
static const char* getqzname | ( | const char * | strp, | |
const int | delim | |||
) | [static] |
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 don't do any checking here; checking is done later in common-case code.
Definition at line 530 of file localtime.c.
Referenced by tzparse().
00531 { 00532 int c; 00533 00534 while ((c = *strp) != '\0' && c != delim) 00535 ++strp; 00536 return strp; 00537 }
static const char* getrule | ( | const char * | strp, | |
struct rule * | rulep | |||
) | [static] |
Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.
Definition at line 637 of file localtime.c.
References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.
Referenced by tzparse().
00638 { 00639 if (*strp == 'J') { 00640 /* 00641 ** Julian day. 00642 */ 00643 rulep->r_type = JULIAN_DAY; 00644 ++strp; 00645 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 00646 } else if (*strp == 'M') { 00647 /* 00648 ** Month, week, day. 00649 */ 00650 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 00651 ++strp; 00652 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 00653 if (strp == NULL) 00654 return NULL; 00655 if (*strp++ != '.') 00656 return NULL; 00657 strp = getnum(strp, &rulep->r_week, 1, 5); 00658 if (strp == NULL) 00659 return NULL; 00660 if (*strp++ != '.') 00661 return NULL; 00662 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 00663 } else if (is_digit(*strp)) { 00664 /* 00665 ** Day of year. 00666 */ 00667 rulep->r_type = DAY_OF_YEAR; 00668 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 00669 } else return NULL; /* invalid format */ 00670 if (strp == NULL) 00671 return NULL; 00672 if (*strp == '/') { 00673 /* 00674 ** Time specified. 00675 */ 00676 ++strp; 00677 strp = getsecs(strp, &rulep->r_time); 00678 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 00679 return strp; 00680 }
static const char* getsecs | ( | const char * | strp, | |
long *const | secsp | |||
) | [static] |
Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.
Definition at line 574 of file localtime.c.
References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.
Referenced by getoffset(), and getrule().
00575 { 00576 int num; 00577 00578 /* 00579 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 00580 ** "M10.4.6/26", which does not conform to Posix, 00581 ** but which specifies the equivalent of 00582 ** ``02:00 on the first Sunday on or after 23 Oct''. 00583 */ 00584 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 00585 if (strp == NULL) 00586 return NULL; 00587 *secsp = num * (long) SECSPERHOUR; 00588 if (*strp == ':') { 00589 ++strp; 00590 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 00591 if (strp == NULL) 00592 return NULL; 00593 *secsp += num * SECSPERMIN; 00594 if (*strp == ':') { 00595 ++strp; 00596 /* `SECSPERMIN' allows for leap seconds. */ 00597 strp = getnum(strp, &num, 0, SECSPERMIN); 00598 if (strp == NULL) 00599 return NULL; 00600 *secsp += num; 00601 } 00602 } 00603 return strp; 00604 }
static const char* getzname | ( | const char * | strp | ) | [static] |
Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.
Definition at line 511 of file localtime.c.
References is_digit.
Referenced by tzparse().
00512 { 00513 char c; 00514 00515 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 00516 c != '+') 00517 ++strp; 00518 return strp; 00519 }
static int gmtload | ( | struct state * | sp | ) | [static] |
static struct tm* gmtsub | ( | const time_t * | timep, | |
const long | offset, | |||
struct tm * | tmp | |||
) | [static, read] |
Definition at line 1154 of file localtime.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, state::chars, gmtload(), state::name, and timesub().
Referenced by localsub().
01155 { 01156 struct tm * result; 01157 struct state *sp; 01158 01159 AST_LIST_LOCK(&zonelist); 01160 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01161 if (!strcmp(sp->name, "UTC")) 01162 break; 01163 } 01164 01165 if (!sp) { 01166 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp))) 01167 return NULL; 01168 gmtload(sp); 01169 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01170 } 01171 AST_LIST_UNLOCK(&zonelist); 01172 01173 result = timesub(timep, offset, sp, tmp); 01174 #ifdef TM_ZONE 01175 /* 01176 ** Could get fancy here and deliver something such as 01177 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 01178 ** but this is no time for a treasure hunt. 01179 */ 01180 if (offset != 0) 01181 tmp->TM_ZONE = " "; 01182 else 01183 tmp->TM_ZONE = sp->chars; 01184 #endif /* defined TM_ZONE */ 01185 return result; 01186 }
static int increment_overflow | ( | int * | number, | |
int | delta | |||
) | [static] |
Simplified normalize logic courtesy Paul Eggert.
Definition at line 1336 of file localtime.c.
Referenced by normalize_overflow(), time2sub(), and timesub().
01337 { 01338 int number0; 01339 01340 number0 = *number; 01341 *number += delta; 01342 return (*number < number0) != (delta < 0); 01343 }
static int leaps_thru_end_of | ( | const int | y | ) | [static] |
Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.
Definition at line 1193 of file localtime.c.
Referenced by timesub().
01194 { 01195 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 01196 -(leaps_thru_end_of(-(y + 1)) + 1); 01197 }
static struct tm* localsub | ( | const time_t * | timep, | |
const long | offset, | |||
struct tm * | tmp, | |||
const struct state * | sp | |||
) | [static, read] |
Definition at line 1056 of file localtime.c.
References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, t, state::timecnt, timesub(), state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.
Referenced by ast_localtime(), and ast_mktime().
01057 { 01058 const struct ttinfo * ttisp; 01059 int i; 01060 struct tm * result; 01061 const time_t t = *timep; 01062 01063 if (sp == NULL) 01064 return gmtsub(timep, offset, tmp); 01065 if ((sp->goback && t < sp->ats[0]) || 01066 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 01067 time_t newt = t; 01068 time_t seconds; 01069 time_t tcycles; 01070 int_fast64_t icycles; 01071 01072 if (t < sp->ats[0]) 01073 seconds = sp->ats[0] - t; 01074 else seconds = t - sp->ats[sp->timecnt - 1]; 01075 --seconds; 01076 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01077 ++tcycles; 01078 icycles = tcycles; 01079 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01080 return NULL; 01081 seconds = icycles; 01082 seconds *= YEARSPERREPEAT; 01083 seconds *= AVGSECSPERYEAR; 01084 if (t < sp->ats[0]) 01085 newt += seconds; 01086 else newt -= seconds; 01087 if (newt < sp->ats[0] || 01088 newt > sp->ats[sp->timecnt - 1]) 01089 return NULL; /* "cannot happen" */ 01090 result = localsub(&newt, offset, tmp, sp); 01091 if (result == tmp) { 01092 time_t newy; 01093 01094 newy = tmp->tm_year; 01095 if (t < sp->ats[0]) 01096 newy -= icycles * YEARSPERREPEAT; 01097 else 01098 newy += icycles * YEARSPERREPEAT; 01099 tmp->tm_year = newy; 01100 if (tmp->tm_year != newy) 01101 return NULL; 01102 } 01103 return result; 01104 } 01105 if (sp->timecnt == 0 || t < sp->ats[0]) { 01106 i = 0; 01107 while (sp->ttis[i].tt_isdst) { 01108 if (++i >= sp->typecnt) { 01109 i = 0; 01110 break; 01111 } 01112 } 01113 } else { 01114 int lo = 1; 01115 int hi = sp->timecnt; 01116 01117 while (lo < hi) { 01118 int mid = (lo + hi) >> 1; 01119 01120 if (t < sp->ats[mid]) 01121 hi = mid; 01122 else 01123 lo = mid + 1; 01124 } 01125 i = (int) sp->types[lo - 1]; 01126 } 01127 ttisp = &sp->ttis[i]; 01128 /* 01129 ** To get (wrong) behavior that's compatible with System V Release 2.0 01130 ** you'd replace the statement below with 01131 ** t += ttisp->tt_gmtoff; 01132 ** timesub(&t, 0L, sp, tmp); 01133 */ 01134 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 01135 tmp->tm_isdst = ttisp->tt_isdst; 01136 tmp->tm_gmtoff = ttisp->tt_gmtoff; 01137 #ifdef TM_ZONE 01138 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 01139 #endif /* defined TM_ZONE */ 01140 return result; 01141 }
static int long_increment_overflow | ( | long * | number, | |
int | delta | |||
) | [static] |
Definition at line 1345 of file localtime.c.
Referenced by long_normalize_overflow(), and time2sub().
01346 { 01347 long number0; 01348 01349 number0 = *number; 01350 *number += delta; 01351 return (*number < number0) != (delta < 0); 01352 }
static int long_normalize_overflow | ( | long * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1365 of file localtime.c.
References long_increment_overflow().
Referenced by time2sub().
01366 { 01367 int tensdelta; 01368 01369 tensdelta = (*unitsptr >= 0) ? 01370 (*unitsptr / base) : 01371 (-1 - (-1 - *unitsptr) / base); 01372 *unitsptr -= tensdelta * base; 01373 return long_increment_overflow(tensptr, tensdelta); 01374 }
static int normalize_overflow | ( | int * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1354 of file localtime.c.
References increment_overflow().
Referenced by time2sub().
01355 { 01356 int tensdelta; 01357 01358 tensdelta = (*unitsptr >= 0) ? 01359 (*unitsptr / base) : 01360 (-1 - (-1 - *unitsptr) / base); 01361 *unitsptr -= tensdelta * base; 01362 return increment_overflow(tensptr, tensdelta); 01363 }
static time_t transtime P | ( | (time_t janfirst, int year, const struct rule *rulep, long offset) | ) | [static] |
static int tmcomp P | ( | (const struct tm *atmp, const struct tm *btmp) | ) | [static] |
static struct tm* timesub P | ( | (const time_t *timep, long offset, const struct state *sp, struct tm *tmp) | ) | [static, read] |
static time_t time2sub P | ( | (struct tm *tmp, struct tm *(*funcp)(const time_t *, long, struct tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp) | ) | [static] |
static time_t time2 P | ( | (struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp) | ) | [static] |
static time_t time1 P | ( | (struct tm *tmp, struct tm *(*funcp) P((const time_t *, long, struct tm *, const struct state *sp)), long offset, const struct state *sp) | ) | [static] |
static int normalize_overflow P | ( | (int *tensptr, int *unitsptr, const int base) | ) | [static] |
static int long_normalize_overflow P | ( | (long *tensptr, int *unitsptr, const int base) | ) | [static] |
static int long_increment_overflow P | ( | (long *number, int delta) | ) | [static] |
static int leaps_thru_end_of P | ( | (int y) | ) | [static] |
static int increment_overflow P | ( | (int *number, int delta) | ) | [static] |
static struct tm* localsub P | ( | (const time_t *timep, long offset, struct tm *tmp, const struct state *sp) | ) | [static, read] |
static struct tm* gmtsub P | ( | (const time_t *timep, long offset, struct tm *tmp) | ) | [static, read] |
static int gmtload P | ( | (struct state *sp) | ) | [static] |
static const char* getrule P | ( | (const char *strp, struct rule *rulep) | ) | [static] |
static const char* getoffset P | ( | (const char *strp, long *offsetp) | ) | [static] |
static const char* getsecs P | ( | (const char *strp, long *secsp) | ) | [static] |
static const char* getnum P | ( | (const char *strp, int *nump, int min, int max) | ) | [static] |
static const char* getqzname P | ( | (const char *strp, const int delim) | ) | [static] |
static const char* getzname P | ( | (const char *strp) | ) | [static] |
static int differ_by_repeat P | ( | (time_t t1, time_t t0) | ) | [static] |
static time_t detzcode64 P | ( | (const char *codep) | ) | [static] |
static time_t time1 | ( | struct tm * | tmp, | |
struct tm *(*)(const time_t *, long, struct tm *, const struct state *) | funcp, | |||
const long | offset, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1576 of file localtime.c.
References FALSE, t, time2(), state::timecnt, TRUE, state::ttis, state::typecnt, state::types, TZ_MAX_TYPES, and WRONG.
Referenced by ast_mktime().
01577 { 01578 time_t t; 01579 int samei, otheri; 01580 int sameind, otherind; 01581 int i; 01582 int nseen; 01583 int seen[TZ_MAX_TYPES]; 01584 int types[TZ_MAX_TYPES]; 01585 int okay; 01586 01587 if (tmp->tm_isdst > 1) 01588 tmp->tm_isdst = 1; 01589 t = time2(tmp, funcp, offset, &okay, sp); 01590 #ifdef PCTS 01591 /* 01592 ** PCTS code courtesy Grant Sullivan. 01593 */ 01594 if (okay) 01595 return t; 01596 if (tmp->tm_isdst < 0) 01597 tmp->tm_isdst = 0; /* reset to std and try again */ 01598 #endif /* defined PCTS */ 01599 #ifndef PCTS 01600 if (okay || tmp->tm_isdst < 0) 01601 return t; 01602 #endif /* !defined PCTS */ 01603 /* 01604 ** We're supposed to assume that somebody took a time of one type 01605 ** and did some math on it that yielded a "struct tm" that's bad. 01606 ** We try to divine the type they started from and adjust to the 01607 ** type they need. 01608 */ 01609 if (sp == NULL) 01610 return WRONG; 01611 for (i = 0; i < sp->typecnt; ++i) 01612 seen[i] = FALSE; 01613 nseen = 0; 01614 for (i = sp->timecnt - 1; i >= 0; --i) 01615 if (!seen[sp->types[i]]) { 01616 seen[sp->types[i]] = TRUE; 01617 types[nseen++] = sp->types[i]; 01618 } 01619 for (sameind = 0; sameind < nseen; ++sameind) { 01620 samei = types[sameind]; 01621 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 01622 continue; 01623 for (otherind = 0; otherind < nseen; ++otherind) { 01624 otheri = types[otherind]; 01625 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 01626 continue; 01627 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 01628 sp->ttis[samei].tt_gmtoff; 01629 tmp->tm_isdst = !tmp->tm_isdst; 01630 t = time2(tmp, funcp, offset, &okay, sp); 01631 if (okay) 01632 return t; 01633 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 01634 sp->ttis[samei].tt_gmtoff; 01635 tmp->tm_isdst = !tmp->tm_isdst; 01636 } 01637 } 01638 return WRONG; 01639 }
static time_t time2 | ( | struct tm * | tmp, | |
struct tm *(*)(const time_t *, long, struct tm *, const struct state *sp) | funcp, | |||
const long | offset, | |||
int * | okayp, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1563 of file localtime.c.
References FALSE, t, time2sub(), and TRUE.
Referenced by time1().
01564 { 01565 time_t t; 01566 01567 /*! \note 01568 ** First try without normalization of seconds 01569 ** (in case tm_sec contains a value associated with a leap second). 01570 ** If that fails, try with normalization of seconds. 01571 */ 01572 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); 01573 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); 01574 }
static time_t time2sub | ( | struct tm * | tmp, | |
struct tm *(*)(const time_t *, long, struct tm *, const struct state *) | funcp, | |||
const long | offset, | |||
int * | okayp, | |||
const int | do_norm_secs, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1389 of file localtime.c.
References DAYSPERLYEAR, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, t, TM_YEAR_BASE, tmcomp(), TRUE, state::ttis, TYPE_BIT, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, WRONG, and year_lengths.
Referenced by time2().
01390 { 01391 int dir; 01392 int i, j; 01393 int saved_seconds; 01394 long li; 01395 time_t lo; 01396 time_t hi; 01397 long y; 01398 time_t newt; 01399 time_t t; 01400 struct tm yourtm, mytm; 01401 01402 *okayp = FALSE; 01403 yourtm = *tmp; 01404 if (do_norm_secs) { 01405 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 01406 SECSPERMIN)) 01407 return WRONG; 01408 } 01409 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 01410 return WRONG; 01411 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 01412 return WRONG; 01413 y = yourtm.tm_year; 01414 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 01415 return WRONG; 01416 /* 01417 ** Turn y into an actual year number for now. 01418 ** It is converted back to an offset from TM_YEAR_BASE later. 01419 */ 01420 if (long_increment_overflow(&y, TM_YEAR_BASE)) 01421 return WRONG; 01422 while (yourtm.tm_mday <= 0) { 01423 if (long_increment_overflow(&y, -1)) 01424 return WRONG; 01425 li = y + (1 < yourtm.tm_mon); 01426 yourtm.tm_mday += year_lengths[isleap(li)]; 01427 } 01428 while (yourtm.tm_mday > DAYSPERLYEAR) { 01429 li = y + (1 < yourtm.tm_mon); 01430 yourtm.tm_mday -= year_lengths[isleap(li)]; 01431 if (long_increment_overflow(&y, 1)) 01432 return WRONG; 01433 } 01434 for ( ; ; ) { 01435 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 01436 if (yourtm.tm_mday <= i) 01437 break; 01438 yourtm.tm_mday -= i; 01439 if (++yourtm.tm_mon >= MONSPERYEAR) { 01440 yourtm.tm_mon = 0; 01441 if (long_increment_overflow(&y, 1)) 01442 return WRONG; 01443 } 01444 } 01445 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 01446 return WRONG; 01447 yourtm.tm_year = y; 01448 if (yourtm.tm_year != y) 01449 return WRONG; 01450 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 01451 saved_seconds = 0; 01452 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 01453 /* 01454 ** We can't set tm_sec to 0, because that might push the 01455 ** time below the minimum representable time. 01456 ** Set tm_sec to 59 instead. 01457 ** This assumes that the minimum representable time is 01458 ** not in the same minute that a leap second was deleted from, 01459 ** which is a safer assumption than using 58 would be. 01460 */ 01461 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 01462 return WRONG; 01463 saved_seconds = yourtm.tm_sec; 01464 yourtm.tm_sec = SECSPERMIN - 1; 01465 } else { 01466 saved_seconds = yourtm.tm_sec; 01467 yourtm.tm_sec = 0; 01468 } 01469 /* 01470 ** Do a binary search (this works whatever time_t's type is). 01471 */ 01472 if (!TYPE_SIGNED(time_t)) { 01473 lo = 0; 01474 hi = lo - 1; 01475 } else if (!TYPE_INTEGRAL(time_t)) { 01476 if (sizeof(time_t) > sizeof(float)) 01477 hi = (time_t) DBL_MAX; 01478 else hi = (time_t) FLT_MAX; 01479 lo = -hi; 01480 } else { 01481 lo = 1; 01482 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 01483 lo *= 2; 01484 hi = -(lo + 1); 01485 } 01486 for ( ; ; ) { 01487 t = lo / 2 + hi / 2; 01488 if (t < lo) 01489 t = lo; 01490 else if (t > hi) 01491 t = hi; 01492 if ((*funcp)(&t, offset, &mytm, sp) == NULL) { 01493 /* 01494 ** Assume that t is too extreme to be represented in 01495 ** a struct tm; arrange things so that it is less 01496 ** extreme on the next pass. 01497 */ 01498 dir = (t > 0) ? 1 : -1; 01499 } else dir = tmcomp(&mytm, &yourtm); 01500 if (dir != 0) { 01501 if (t == lo) { 01502 ++t; 01503 if (t <= lo) 01504 return WRONG; 01505 ++lo; 01506 } else if (t == hi) { 01507 --t; 01508 if (t >= hi) 01509 return WRONG; 01510 --hi; 01511 } 01512 if (lo > hi) 01513 return WRONG; 01514 if (dir > 0) 01515 hi = t; 01516 else lo = t; 01517 continue; 01518 } 01519 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 01520 break; 01521 /* 01522 ** Right time, wrong type. 01523 ** Hunt for right time, right type. 01524 ** It's okay to guess wrong since the guess 01525 ** gets checked. 01526 */ 01527 /* 01528 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 01529 */ 01530 for (i = sp->typecnt - 1; i >= 0; --i) { 01531 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 01532 continue; 01533 for (j = sp->typecnt - 1; j >= 0; --j) { 01534 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 01535 continue; 01536 newt = t + sp->ttis[j].tt_gmtoff - 01537 sp->ttis[i].tt_gmtoff; 01538 if ((*funcp)(&newt, offset, &mytm, sp) == NULL) 01539 continue; 01540 if (tmcomp(&mytm, &yourtm) != 0) 01541 continue; 01542 if (mytm.tm_isdst != yourtm.tm_isdst) 01543 continue; 01544 /* 01545 ** We have a match. 01546 */ 01547 t = newt; 01548 goto label; 01549 } 01550 } 01551 return WRONG; 01552 } 01553 label: 01554 newt = t + saved_seconds; 01555 if ((newt < t) != (saved_seconds < 0)) 01556 return WRONG; 01557 t = newt; 01558 if ((*funcp)(&t, offset, tmp, sp)) 01559 *okayp = TRUE; 01560 return t; 01561 }
static struct tm* timesub | ( | const time_t * | timep, | |
const long | offset, | |||
const struct state * | sp, | |||
struct tm * | tmp | |||
) | [static, read] |
Definition at line 1199 of file localtime.c.
References DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, increment_overflow(), isleap, state::leapcnt, leaps_thru_end_of(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, mon_lengths, SECSPERDAY, SECSPERHOUR, SECSPERMIN, TM_YEAR_BASE, and year_lengths.
Referenced by gmtsub(), and localsub().
01200 { 01201 const struct lsinfo * lp; 01202 time_t tdays; 01203 int idays; /* unsigned would be so 2003 */ 01204 long rem; 01205 int y; 01206 const int * ip; 01207 long corr; 01208 int hit; 01209 int i; 01210 long seconds; 01211 01212 01213 corr = 0; 01214 hit = 0; 01215 i = (sp == NULL) ? 0 : sp->leapcnt; 01216 while (--i >= 0) { 01217 lp = &sp->lsis[i]; 01218 if (*timep >= lp->ls_trans) { 01219 if (*timep == lp->ls_trans) { 01220 hit = ((i == 0 && lp->ls_corr > 0) || 01221 lp->ls_corr > sp->lsis[i - 1].ls_corr); 01222 if (hit) 01223 while (i > 0 && 01224 sp->lsis[i].ls_trans == 01225 sp->lsis[i - 1].ls_trans + 1 && 01226 sp->lsis[i].ls_corr == 01227 sp->lsis[i - 1].ls_corr + 1) { 01228 ++hit; 01229 --i; 01230 } 01231 } 01232 corr = lp->ls_corr; 01233 break; 01234 } 01235 } 01236 y = EPOCH_YEAR; 01237 tdays = *timep / SECSPERDAY; 01238 rem = *timep - tdays * SECSPERDAY; 01239 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 01240 int newy; 01241 time_t tdelta; 01242 int idelta; 01243 int leapdays; 01244 01245 tdelta = tdays / DAYSPERLYEAR; 01246 idelta = tdelta; 01247 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 01248 return NULL; 01249 if (idelta == 0) 01250 idelta = (tdays < 0) ? -1 : 1; 01251 newy = y; 01252 if (increment_overflow(&newy, idelta)) 01253 return NULL; 01254 leapdays = leaps_thru_end_of(newy - 1) - 01255 leaps_thru_end_of(y - 1); 01256 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 01257 tdays -= leapdays; 01258 y = newy; 01259 } 01260 01261 seconds = tdays * SECSPERDAY + 0.5; 01262 tdays = seconds / SECSPERDAY; 01263 rem += seconds - tdays * SECSPERDAY; 01264 01265 /* 01266 ** Given the range, we can now fearlessly cast... 01267 */ 01268 idays = tdays; 01269 rem += offset - corr; 01270 while (rem < 0) { 01271 rem += SECSPERDAY; 01272 --idays; 01273 } 01274 while (rem >= SECSPERDAY) { 01275 rem -= SECSPERDAY; 01276 ++idays; 01277 } 01278 while (idays < 0) { 01279 if (increment_overflow(&y, -1)) 01280 return NULL; 01281 idays += year_lengths[isleap(y)]; 01282 } 01283 while (idays >= year_lengths[isleap(y)]) { 01284 idays -= year_lengths[isleap(y)]; 01285 if (increment_overflow(&y, 1)) 01286 return NULL; 01287 } 01288 tmp->tm_year = y; 01289 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 01290 return NULL; 01291 tmp->tm_yday = idays; 01292 /* 01293 ** The "extra" mods below avoid overflow problems. 01294 */ 01295 tmp->tm_wday = EPOCH_WDAY + 01296 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 01297 (DAYSPERNYEAR % DAYSPERWEEK) + 01298 leaps_thru_end_of(y - 1) - 01299 leaps_thru_end_of(EPOCH_YEAR - 1) + 01300 idays; 01301 tmp->tm_wday %= DAYSPERWEEK; 01302 if (tmp->tm_wday < 0) 01303 tmp->tm_wday += DAYSPERWEEK; 01304 tmp->tm_hour = (int) (rem / SECSPERHOUR); 01305 rem %= SECSPERHOUR; 01306 tmp->tm_min = (int) (rem / SECSPERMIN); 01307 /* 01308 ** A positive leap second requires a special 01309 ** representation. This uses "... ??:59:60" et seq. 01310 */ 01311 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 01312 ip = mon_lengths[isleap(y)]; 01313 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 01314 idays -= ip[tmp->tm_mon]; 01315 tmp->tm_mday = (int) (idays + 1); 01316 tmp->tm_isdst = 0; 01317 #ifdef TM_GMTOFF 01318 tmp->TM_GMTOFF = offset; 01319 #endif /* defined TM_GMTOFF */ 01320 return tmp; 01321 }
static int tmcomp | ( | const struct tm * | atmp, | |
const struct tm * | btmp | |||
) | [static] |
Definition at line 1376 of file localtime.c.
Referenced by time2sub().
01377 { 01378 int result; 01379 01380 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 01381 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 01382 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 01383 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 01384 (result = (atmp->tm_min - btmp->tm_min)) == 0) 01385 result = atmp->tm_sec - btmp->tm_sec; 01386 return result; 01387 }
static time_t transtime | ( | const time_t | janfirst, | |
const int | year, | |||
const struct rule * | rulep, | |||
const long | offset | |||
) | [static] |
Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
Definition at line 688 of file localtime.c.
References DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, m1, mon_lengths, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERDAY.
Referenced by tzparse().
00689 { 00690 int leapyear; 00691 time_t value; 00692 int i; 00693 int d, m1, yy0, yy1, yy2, dow; 00694 00695 INITIALIZE(value); 00696 leapyear = isleap(year); 00697 switch (rulep->r_type) { 00698 00699 case JULIAN_DAY: 00700 /* 00701 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 00702 ** years. 00703 ** In non-leap years, or if the day number is 59 or less, just 00704 ** add SECSPERDAY times the day number-1 to the time of 00705 ** January 1, midnight, to get the day. 00706 */ 00707 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 00708 if (leapyear && rulep->r_day >= 60) 00709 value += SECSPERDAY; 00710 break; 00711 00712 case DAY_OF_YEAR: 00713 /* 00714 ** n - day of year. 00715 ** Just add SECSPERDAY times the day number to the time of 00716 ** January 1, midnight, to get the day. 00717 */ 00718 value = janfirst + rulep->r_day * SECSPERDAY; 00719 break; 00720 00721 case MONTH_NTH_DAY_OF_WEEK: 00722 /* 00723 ** Mm.n.d - nth "dth day" of month m. 00724 */ 00725 value = janfirst; 00726 for (i = 0; i < rulep->r_mon - 1; ++i) 00727 value += mon_lengths[leapyear][i] * SECSPERDAY; 00728 00729 /* 00730 ** Use Zeller's Congruence to get day-of-week of first day of 00731 ** month. 00732 */ 00733 m1 = (rulep->r_mon + 9) % 12 + 1; 00734 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 00735 yy1 = yy0 / 100; 00736 yy2 = yy0 % 100; 00737 dow = ((26 * m1 - 2) / 10 + 00738 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 00739 if (dow < 0) 00740 dow += DAYSPERWEEK; 00741 00742 /* 00743 ** "dow" is the day-of-week of the first day of the month. Get 00744 ** the day-of-month (zero-origin) of the first "dow" day of the 00745 ** month. 00746 */ 00747 d = rulep->r_day - dow; 00748 if (d < 0) 00749 d += DAYSPERWEEK; 00750 for (i = 1; i < rulep->r_week; ++i) { 00751 if (d + DAYSPERWEEK >= 00752 mon_lengths[leapyear][rulep->r_mon - 1]) 00753 break; 00754 d += DAYSPERWEEK; 00755 } 00756 00757 /* 00758 ** "d" is the day-of-month (zero-origin) of the day we want. 00759 */ 00760 value += d * SECSPERDAY; 00761 break; 00762 } 00763 00764 /* 00765 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 00766 ** question. To get the Epoch-relative time of the specified local 00767 ** time on that day, add the transition time and the current offset 00768 ** from UTC. 00769 */ 00770 return value + rulep->r_time + offset; 00771 }
static int tzload | ( | const char * | name, | |
struct state *const | sp, | |||
const int | doextend | |||
) | [static] |
Definition at line 266 of file localtime.c.
References state::ats, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, FILENAME_MAX, state::goahead, state::goback, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, state::ttis, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, tzparse(), WRONG, and YEARSPERREPEAT.
Referenced by ast_tzset(), gmtload(), and tzparse().
00267 { 00268 const char * p; 00269 int i; 00270 int fid; 00271 int stored; 00272 int nread; 00273 union { 00274 struct tzhead tzhead; 00275 char buf[2 * sizeof(struct tzhead) + 00276 2 * sizeof *sp + 00277 4 * TZ_MAX_TIMES]; 00278 } u; 00279 00280 if (name == NULL && (name = TZDEFAULT) == NULL) 00281 return WRONG; 00282 { 00283 int doaccess; 00284 /* 00285 ** Section 4.9.1 of the C standard says that 00286 ** "FILENAME_MAX expands to an integral constant expression 00287 ** that is the size needed for an array of char large enough 00288 ** to hold the longest file name string that the implementation 00289 ** guarantees can be opened." 00290 */ 00291 char fullname[FILENAME_MAX + 1]; 00292 00293 if (name[0] == ':') 00294 ++name; 00295 doaccess = name[0] == '/'; 00296 if (!doaccess) { 00297 if ((p = TZDIR) == NULL) 00298 return WRONG; 00299 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 00300 return WRONG; 00301 (void) strcpy(fullname, p); 00302 (void) strcat(fullname, "/"); 00303 (void) strcat(fullname, name); 00304 /* 00305 ** Set doaccess if '.' (as in "../") shows up in name. 00306 */ 00307 if (strchr(name, '.') != NULL) 00308 doaccess = TRUE; 00309 name = fullname; 00310 } 00311 if (doaccess && access(name, R_OK) != 0) 00312 return WRONG; 00313 if ((fid = open(name, OPEN_MODE)) == -1) 00314 return WRONG; 00315 } 00316 nread = read(fid, u.buf, sizeof u.buf); 00317 if (close(fid) < 0 || nread <= 0) 00318 return WRONG; 00319 for (stored = 4; stored <= 8; stored *= 2) { 00320 int ttisstdcnt; 00321 int ttisgmtcnt; 00322 00323 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 00324 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 00325 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 00326 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 00327 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 00328 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 00329 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 00330 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 00331 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 00332 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 00333 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 00334 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 00335 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 00336 return WRONG; 00337 if (nread - (p - u.buf) < 00338 sp->timecnt * stored + /* ats */ 00339 sp->timecnt + /* types */ 00340 sp->typecnt * 6 + /* ttinfos */ 00341 sp->charcnt + /* chars */ 00342 sp->leapcnt * (stored + 4) + /* lsinfos */ 00343 ttisstdcnt + /* ttisstds */ 00344 ttisgmtcnt) /* ttisgmts */ 00345 return WRONG; 00346 for (i = 0; i < sp->timecnt; ++i) { 00347 sp->ats[i] = (stored == 4) ? 00348 detzcode(p) : detzcode64(p); 00349 p += stored; 00350 } 00351 for (i = 0; i < sp->timecnt; ++i) { 00352 sp->types[i] = (unsigned char) *p++; 00353 if (sp->types[i] >= sp->typecnt) 00354 return WRONG; 00355 } 00356 for (i = 0; i < sp->typecnt; ++i) { 00357 struct ttinfo * ttisp; 00358 00359 ttisp = &sp->ttis[i]; 00360 ttisp->tt_gmtoff = detzcode(p); 00361 p += 4; 00362 ttisp->tt_isdst = (unsigned char) *p++; 00363 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 00364 return WRONG; 00365 ttisp->tt_abbrind = (unsigned char) *p++; 00366 if (ttisp->tt_abbrind < 0 || 00367 ttisp->tt_abbrind > sp->charcnt) 00368 return WRONG; 00369 } 00370 for (i = 0; i < sp->charcnt; ++i) 00371 sp->chars[i] = *p++; 00372 sp->chars[i] = '\0'; /* ensure '\0' at end */ 00373 for (i = 0; i < sp->leapcnt; ++i) { 00374 struct lsinfo * lsisp; 00375 00376 lsisp = &sp->lsis[i]; 00377 lsisp->ls_trans = (stored == 4) ? 00378 detzcode(p) : detzcode64(p); 00379 p += stored; 00380 lsisp->ls_corr = detzcode(p); 00381 p += 4; 00382 } 00383 for (i = 0; i < sp->typecnt; ++i) { 00384 struct ttinfo * ttisp; 00385 00386 ttisp = &sp->ttis[i]; 00387 if (ttisstdcnt == 0) 00388 ttisp->tt_ttisstd = FALSE; 00389 else { 00390 ttisp->tt_ttisstd = *p++; 00391 if (ttisp->tt_ttisstd != TRUE && 00392 ttisp->tt_ttisstd != FALSE) 00393 return WRONG; 00394 } 00395 } 00396 for (i = 0; i < sp->typecnt; ++i) { 00397 struct ttinfo * ttisp; 00398 00399 ttisp = &sp->ttis[i]; 00400 if (ttisgmtcnt == 0) 00401 ttisp->tt_ttisgmt = FALSE; 00402 else { 00403 ttisp->tt_ttisgmt = *p++; 00404 if (ttisp->tt_ttisgmt != TRUE && 00405 ttisp->tt_ttisgmt != FALSE) 00406 return WRONG; 00407 } 00408 } 00409 /* 00410 ** Out-of-sort ats should mean we're running on a 00411 ** signed time_t system but using a data file with 00412 ** unsigned values (or vice versa). 00413 */ 00414 for (i = 0; i < sp->timecnt - 2; ++i) 00415 if (sp->ats[i] > sp->ats[i + 1]) { 00416 ++i; 00417 if (TYPE_SIGNED(time_t)) { 00418 /* 00419 ** Ignore the end (easy). 00420 */ 00421 sp->timecnt = i; 00422 } else { 00423 /* 00424 ** Ignore the beginning (harder). 00425 */ 00426 int j; 00427 00428 for (j = 0; j + i < sp->timecnt; ++j) { 00429 sp->ats[j] = sp->ats[j + i]; 00430 sp->types[j] = sp->types[j + i]; 00431 } 00432 sp->timecnt = j; 00433 } 00434 break; 00435 } 00436 /* 00437 ** If this is an old file, we're done. 00438 */ 00439 if (u.tzhead.tzh_version[0] == '\0') 00440 break; 00441 nread -= p - u.buf; 00442 for (i = 0; i < nread; ++i) 00443 u.buf[i] = p[i]; 00444 /* 00445 ** If this is a narrow integer time_t system, we're done. 00446 */ 00447 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 00448 break; 00449 } 00450 if (doextend && nread > 2 && 00451 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 00452 sp->typecnt + 2 <= TZ_MAX_TYPES) { 00453 struct state ts; 00454 int result; 00455 00456 u.buf[nread - 1] = '\0'; 00457 result = tzparse(&u.buf[1], &ts, FALSE); 00458 if (result == 0 && ts.typecnt == 2 && 00459 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 00460 for (i = 0; i < 2; ++i) 00461 ts.ttis[i].tt_abbrind += 00462 sp->charcnt; 00463 for (i = 0; i < ts.charcnt; ++i) 00464 sp->chars[sp->charcnt++] = 00465 ts.chars[i]; 00466 i = 0; 00467 while (i < ts.timecnt && 00468 ts.ats[i] <= 00469 sp->ats[sp->timecnt - 1]) 00470 ++i; 00471 while (i < ts.timecnt && 00472 sp->timecnt < TZ_MAX_TIMES) { 00473 sp->ats[sp->timecnt] = 00474 ts.ats[i]; 00475 sp->types[sp->timecnt] = 00476 sp->typecnt + 00477 ts.types[i]; 00478 ++sp->timecnt; 00479 ++i; 00480 } 00481 sp->ttis[sp->typecnt++] = ts.ttis[0]; 00482 sp->ttis[sp->typecnt++] = ts.ttis[1]; 00483 } 00484 } 00485 i = 2 * YEARSPERREPEAT; 00486 sp->goback = sp->goahead = sp->timecnt > i; 00487 sp->goback = sp->goback && sp->types[i] == sp->types[0] && 00488 differ_by_repeat(sp->ats[i], sp->ats[0]); 00489 sp->goahead = sp->goahead && 00490 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && 00491 differ_by_repeat(sp->ats[sp->timecnt - 1], 00492 sp->ats[sp->timecnt - 1 - i]); 00493 return 0; 00494 }
static int tzparse | ( | const char * | name, | |
struct state * | sp, | |||
const int | lastditch | |||
) | [static] |
Definition at line 778 of file localtime.c.
References state::ats, state::charcnt, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, starttime, state::timecnt, transtime(), TRUE, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, TZDEFRULESTRING, tzload(), WRONG, and year_lengths.
Referenced by ast_tzset(), gmtload(), and tzload().
00779 { 00780 const char * stdname; 00781 const char * dstname; 00782 size_t stdlen; 00783 size_t dstlen; 00784 long stdoffset; 00785 long dstoffset; 00786 time_t * atp; 00787 unsigned char * typep; 00788 char * cp; 00789 int load_result; 00790 00791 INITIALIZE(dstname); 00792 stdname = name; 00793 if (lastditch) { 00794 stdlen = strlen(name); /* length of standard zone name */ 00795 name += stdlen; 00796 if (stdlen >= sizeof sp->chars) 00797 stdlen = (sizeof sp->chars) - 1; 00798 stdoffset = 0; 00799 } else { 00800 if (*name == '<') { 00801 name++; 00802 stdname = name; 00803 name = getqzname(name, '>'); 00804 if (*name != '>') 00805 return WRONG; 00806 stdlen = name - stdname; 00807 name++; 00808 } else { 00809 name = getzname(name); 00810 stdlen = name - stdname; 00811 } 00812 if (*name == '\0') 00813 return WRONG; 00814 name = getoffset(name, &stdoffset); 00815 if (name == NULL) 00816 return WRONG; 00817 } 00818 load_result = tzload(TZDEFRULES, sp, FALSE); 00819 if (load_result != 0) 00820 sp->leapcnt = 0; /* so, we're off a little */ 00821 if (*name != '\0') { 00822 if (*name == '<') { 00823 dstname = ++name; 00824 name = getqzname(name, '>'); 00825 if (*name != '>') 00826 return WRONG; 00827 dstlen = name - dstname; 00828 name++; 00829 } else { 00830 dstname = name; 00831 name = getzname(name); 00832 dstlen = name - dstname; /* length of DST zone name */ 00833 } 00834 if (*name != '\0' && *name != ',' && *name != ';') { 00835 name = getoffset(name, &dstoffset); 00836 if (name == NULL) 00837 return WRONG; 00838 } else dstoffset = stdoffset - SECSPERHOUR; 00839 if (*name == '\0' && load_result != 0) 00840 name = TZDEFRULESTRING; 00841 if (*name == ',' || *name == ';') { 00842 struct rule start; 00843 struct rule end; 00844 int year; 00845 time_t janfirst; 00846 time_t starttime; 00847 time_t endtime; 00848 00849 ++name; 00850 if ((name = getrule(name, &start)) == NULL) 00851 return WRONG; 00852 if (*name++ != ',') 00853 return WRONG; 00854 if ((name = getrule(name, &end)) == NULL) 00855 return WRONG; 00856 if (*name != '\0') 00857 return WRONG; 00858 sp->typecnt = 2; /* standard time and DST */ 00859 /* 00860 ** Two transitions per year, from EPOCH_YEAR forward. 00861 */ 00862 sp->ttis[0].tt_gmtoff = -dstoffset; 00863 sp->ttis[0].tt_isdst = 1; 00864 sp->ttis[0].tt_abbrind = stdlen + 1; 00865 sp->ttis[1].tt_gmtoff = -stdoffset; 00866 sp->ttis[1].tt_isdst = 0; 00867 sp->ttis[1].tt_abbrind = 0; 00868 atp = sp->ats; 00869 typep = sp->types; 00870 janfirst = 0; 00871 sp->timecnt = 0; 00872 for (year = EPOCH_YEAR; 00873 sp->timecnt + 2 <= TZ_MAX_TIMES; 00874 ++year) { 00875 time_t newfirst; 00876 00877 starttime = transtime(janfirst, year, &start, 00878 stdoffset); 00879 endtime = transtime(janfirst, year, &end, 00880 dstoffset); 00881 if (starttime > endtime) { 00882 *atp++ = endtime; 00883 *typep++ = 1; /* DST ends */ 00884 *atp++ = starttime; 00885 *typep++ = 0; /* DST begins */ 00886 } else { 00887 *atp++ = starttime; 00888 *typep++ = 0; /* DST begins */ 00889 *atp++ = endtime; 00890 *typep++ = 1; /* DST ends */ 00891 } 00892 sp->timecnt += 2; 00893 newfirst = janfirst; 00894 newfirst += year_lengths[isleap(year)] * 00895 SECSPERDAY; 00896 if (newfirst <= janfirst) 00897 break; 00898 janfirst = newfirst; 00899 } 00900 } else { 00901 long theirstdoffset; 00902 long theirdstoffset; 00903 long theiroffset; 00904 int isdst; 00905 int i; 00906 int j; 00907 00908 if (*name != '\0') 00909 return WRONG; 00910 /* 00911 ** Initial values of theirstdoffset and theirdstoffset. 00912 */ 00913 theirstdoffset = 0; 00914 for (i = 0; i < sp->timecnt; ++i) { 00915 j = sp->types[i]; 00916 if (!sp->ttis[j].tt_isdst) { 00917 theirstdoffset = 00918 -sp->ttis[j].tt_gmtoff; 00919 break; 00920 } 00921 } 00922 theirdstoffset = 0; 00923 for (i = 0; i < sp->timecnt; ++i) { 00924 j = sp->types[i]; 00925 if (sp->ttis[j].tt_isdst) { 00926 theirdstoffset = 00927 -sp->ttis[j].tt_gmtoff; 00928 break; 00929 } 00930 } 00931 /* 00932 ** Initially we're assumed to be in standard time. 00933 */ 00934 isdst = FALSE; 00935 theiroffset = theirstdoffset; 00936 /* 00937 ** Now juggle transition times and types 00938 ** tracking offsets as you do. 00939 */ 00940 for (i = 0; i < sp->timecnt; ++i) { 00941 j = sp->types[i]; 00942 sp->types[i] = sp->ttis[j].tt_isdst; 00943 if (sp->ttis[j].tt_ttisgmt) { 00944 /* No adjustment to transition time */ 00945 } else { 00946 /* 00947 ** If summer time is in effect, and the 00948 ** transition time was not specified as 00949 ** standard time, add the summer time 00950 ** offset to the transition time; 00951 ** otherwise, add the standard time 00952 ** offset to the transition time. 00953 */ 00954 /* 00955 ** Transitions from DST to DDST 00956 ** will effectively disappear since 00957 ** POSIX provides for only one DST 00958 ** offset. 00959 */ 00960 if (isdst && !sp->ttis[j].tt_ttisstd) { 00961 sp->ats[i] += dstoffset - 00962 theirdstoffset; 00963 } else { 00964 sp->ats[i] += stdoffset - 00965 theirstdoffset; 00966 } 00967 } 00968 theiroffset = -sp->ttis[j].tt_gmtoff; 00969 if (sp->ttis[j].tt_isdst) 00970 theirdstoffset = theiroffset; 00971 else theirstdoffset = theiroffset; 00972 } 00973 /* 00974 ** Finally, fill in ttis. 00975 ** ttisstd and ttisgmt need not be handled. 00976 */ 00977 sp->ttis[0].tt_gmtoff = -stdoffset; 00978 sp->ttis[0].tt_isdst = FALSE; 00979 sp->ttis[0].tt_abbrind = 0; 00980 sp->ttis[1].tt_gmtoff = -dstoffset; 00981 sp->ttis[1].tt_isdst = TRUE; 00982 sp->ttis[1].tt_abbrind = stdlen + 1; 00983 sp->typecnt = 2; 00984 } 00985 } else { 00986 dstlen = 0; 00987 sp->typecnt = 1; /* only standard time */ 00988 sp->timecnt = 0; 00989 sp->ttis[0].tt_gmtoff = -stdoffset; 00990 sp->ttis[0].tt_isdst = 0; 00991 sp->ttis[0].tt_abbrind = 0; 00992 } 00993 sp->charcnt = stdlen + 1; 00994 if (dstlen != 0) 00995 sp->charcnt += dstlen + 1; 00996 if ((size_t) sp->charcnt > sizeof sp->chars) 00997 return WRONG; 00998 cp = sp->chars; 00999 (void) strncpy(cp, stdname, stdlen); 01000 cp += stdlen; 01001 *cp++ = '\0'; 01002 if (dstlen != 0) { 01003 (void) strncpy(cp, dstname, dstlen); 01004 *(cp + dstlen) = '\0'; 01005 } 01006 return 0; 01007 }
const int mon_lengths[2][MONSPERYEAR] [static] |
Initial value:
{ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }
Definition at line 496 of file localtime.c.
Referenced by time2sub(), timesub(), and transtime().
const int year_lengths[2] [static] |
Initial value:
{ DAYSPERNYEAR, DAYSPERLYEAR }
Definition at line 501 of file localtime.c.
Referenced by time2sub(), timesub(), and tzparse().