#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 1145 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().
01146 { 01147 const struct state *sp = ast_tzset(zone); 01148 memset(tmp, 0, sizeof(*tmp)); 01149 return sp ? localsub(timep, 0L, tmp, sp) : NULL; 01150 }
time_t ast_mktime | ( | struct tm * | tmp, | |
const char * | zone | |||
) |
Definition at line 1643 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime(), sms_readfile(), and unpackdate().
01644 { 01645 const struct state *sp; 01646 if (!(sp = ast_tzset(zone))) 01647 return 0; 01648 return time1(tmp, localsub, 0L, sp); 01649 }
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.
References int_fast64_t.
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 1156 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().
01157 { 01158 struct tm * result; 01159 struct state *sp; 01160 01161 AST_LIST_LOCK(&zonelist); 01162 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01163 if (!strcmp(sp->name, "UTC")) 01164 break; 01165 } 01166 01167 if (!sp) { 01168 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp))) 01169 return NULL; 01170 gmtload(sp); 01171 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01172 } 01173 AST_LIST_UNLOCK(&zonelist); 01174 01175 result = timesub(timep, offset, sp, tmp); 01176 #ifdef TM_ZONE 01177 /* 01178 ** Could get fancy here and deliver something such as 01179 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 01180 ** but this is no time for a treasure hunt. 01181 */ 01182 if (offset != 0) 01183 tmp->TM_ZONE = " "; 01184 else 01185 tmp->TM_ZONE = sp->chars; 01186 #endif /* defined TM_ZONE */ 01187 return result; 01188 }
static int increment_overflow | ( | int * | number, | |
int | delta | |||
) | [static] |
Simplified normalize logic courtesy Paul Eggert.
Definition at line 1338 of file localtime.c.
Referenced by normalize_overflow(), time2sub(), and timesub().
01339 { 01340 int number0; 01341 01342 number0 = *number; 01343 *number += delta; 01344 return (*number < number0) != (delta < 0); 01345 }
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 1195 of file localtime.c.
Referenced by timesub().
01196 { 01197 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 01198 -(leaps_thru_end_of(-(y + 1)) + 1); 01199 }
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, int_fast64_t, 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 #ifndef SOLARIS /* Solaris doesn't have this element */ 01137 tmp->tm_gmtoff = ttisp->tt_gmtoff; 01138 #endif 01139 #ifdef TM_ZONE 01140 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 01141 #endif /* defined TM_ZONE */ 01142 return result; 01143 }
static int long_increment_overflow | ( | long * | number, | |
int | delta | |||
) | [static] |
Definition at line 1347 of file localtime.c.
Referenced by long_normalize_overflow(), and time2sub().
01348 { 01349 long number0; 01350 01351 number0 = *number; 01352 *number += delta; 01353 return (*number < number0) != (delta < 0); 01354 }
static int long_normalize_overflow | ( | long * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1367 of file localtime.c.
References long_increment_overflow().
Referenced by time2sub().
01368 { 01369 int tensdelta; 01370 01371 tensdelta = (*unitsptr >= 0) ? 01372 (*unitsptr / base) : 01373 (-1 - (-1 - *unitsptr) / base); 01374 *unitsptr -= tensdelta * base; 01375 return long_increment_overflow(tensptr, tensdelta); 01376 }
static int normalize_overflow | ( | int * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1356 of file localtime.c.
References increment_overflow().
Referenced by time2sub().
01357 { 01358 int tensdelta; 01359 01360 tensdelta = (*unitsptr >= 0) ? 01361 (*unitsptr / base) : 01362 (-1 - (-1 - *unitsptr) / base); 01363 *unitsptr -= tensdelta * base; 01364 return increment_overflow(tensptr, tensdelta); 01365 }
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 1578 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().
01579 { 01580 time_t t; 01581 int samei, otheri; 01582 int sameind, otherind; 01583 int i; 01584 int nseen; 01585 int seen[TZ_MAX_TYPES]; 01586 int types[TZ_MAX_TYPES]; 01587 int okay; 01588 01589 if (tmp->tm_isdst > 1) 01590 tmp->tm_isdst = 1; 01591 t = time2(tmp, funcp, offset, &okay, sp); 01592 #ifdef PCTS 01593 /* 01594 ** PCTS code courtesy Grant Sullivan. 01595 */ 01596 if (okay) 01597 return t; 01598 if (tmp->tm_isdst < 0) 01599 tmp->tm_isdst = 0; /* reset to std and try again */ 01600 #endif /* defined PCTS */ 01601 #ifndef PCTS 01602 if (okay || tmp->tm_isdst < 0) 01603 return t; 01604 #endif /* !defined PCTS */ 01605 /* 01606 ** We're supposed to assume that somebody took a time of one type 01607 ** and did some math on it that yielded a "struct tm" that's bad. 01608 ** We try to divine the type they started from and adjust to the 01609 ** type they need. 01610 */ 01611 if (sp == NULL) 01612 return WRONG; 01613 for (i = 0; i < sp->typecnt; ++i) 01614 seen[i] = FALSE; 01615 nseen = 0; 01616 for (i = sp->timecnt - 1; i >= 0; --i) 01617 if (!seen[sp->types[i]]) { 01618 seen[sp->types[i]] = TRUE; 01619 types[nseen++] = sp->types[i]; 01620 } 01621 for (sameind = 0; sameind < nseen; ++sameind) { 01622 samei = types[sameind]; 01623 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 01624 continue; 01625 for (otherind = 0; otherind < nseen; ++otherind) { 01626 otheri = types[otherind]; 01627 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 01628 continue; 01629 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 01630 sp->ttis[samei].tt_gmtoff; 01631 tmp->tm_isdst = !tmp->tm_isdst; 01632 t = time2(tmp, funcp, offset, &okay, sp); 01633 if (okay) 01634 return t; 01635 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 01636 sp->ttis[samei].tt_gmtoff; 01637 tmp->tm_isdst = !tmp->tm_isdst; 01638 } 01639 } 01640 return WRONG; 01641 }
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 1565 of file localtime.c.
References FALSE, t, time2sub(), and TRUE.
Referenced by time1().
01566 { 01567 time_t t; 01568 01569 /*! \note 01570 ** First try without normalization of seconds 01571 ** (in case tm_sec contains a value associated with a leap second). 01572 ** If that fails, try with normalization of seconds. 01573 */ 01574 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); 01575 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); 01576 }
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 1391 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().
01392 { 01393 int dir; 01394 int i, j; 01395 int saved_seconds; 01396 long li; 01397 time_t lo; 01398 time_t hi; 01399 long y; 01400 time_t newt; 01401 time_t t; 01402 struct tm yourtm, mytm; 01403 01404 *okayp = FALSE; 01405 yourtm = *tmp; 01406 if (do_norm_secs) { 01407 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 01408 SECSPERMIN)) 01409 return WRONG; 01410 } 01411 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 01412 return WRONG; 01413 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 01414 return WRONG; 01415 y = yourtm.tm_year; 01416 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 01417 return WRONG; 01418 /* 01419 ** Turn y into an actual year number for now. 01420 ** It is converted back to an offset from TM_YEAR_BASE later. 01421 */ 01422 if (long_increment_overflow(&y, TM_YEAR_BASE)) 01423 return WRONG; 01424 while (yourtm.tm_mday <= 0) { 01425 if (long_increment_overflow(&y, -1)) 01426 return WRONG; 01427 li = y + (1 < yourtm.tm_mon); 01428 yourtm.tm_mday += year_lengths[isleap(li)]; 01429 } 01430 while (yourtm.tm_mday > DAYSPERLYEAR) { 01431 li = y + (1 < yourtm.tm_mon); 01432 yourtm.tm_mday -= year_lengths[isleap(li)]; 01433 if (long_increment_overflow(&y, 1)) 01434 return WRONG; 01435 } 01436 for ( ; ; ) { 01437 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 01438 if (yourtm.tm_mday <= i) 01439 break; 01440 yourtm.tm_mday -= i; 01441 if (++yourtm.tm_mon >= MONSPERYEAR) { 01442 yourtm.tm_mon = 0; 01443 if (long_increment_overflow(&y, 1)) 01444 return WRONG; 01445 } 01446 } 01447 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 01448 return WRONG; 01449 yourtm.tm_year = y; 01450 if (yourtm.tm_year != y) 01451 return WRONG; 01452 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 01453 saved_seconds = 0; 01454 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 01455 /* 01456 ** We can't set tm_sec to 0, because that might push the 01457 ** time below the minimum representable time. 01458 ** Set tm_sec to 59 instead. 01459 ** This assumes that the minimum representable time is 01460 ** not in the same minute that a leap second was deleted from, 01461 ** which is a safer assumption than using 58 would be. 01462 */ 01463 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 01464 return WRONG; 01465 saved_seconds = yourtm.tm_sec; 01466 yourtm.tm_sec = SECSPERMIN - 1; 01467 } else { 01468 saved_seconds = yourtm.tm_sec; 01469 yourtm.tm_sec = 0; 01470 } 01471 /* 01472 ** Do a binary search (this works whatever time_t's type is). 01473 */ 01474 if (!TYPE_SIGNED(time_t)) { 01475 lo = 0; 01476 hi = lo - 1; 01477 } else if (!TYPE_INTEGRAL(time_t)) { 01478 if (sizeof(time_t) > sizeof(float)) 01479 hi = (time_t) DBL_MAX; 01480 else hi = (time_t) FLT_MAX; 01481 lo = -hi; 01482 } else { 01483 lo = 1; 01484 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 01485 lo *= 2; 01486 hi = -(lo + 1); 01487 } 01488 for ( ; ; ) { 01489 t = lo / 2 + hi / 2; 01490 if (t < lo) 01491 t = lo; 01492 else if (t > hi) 01493 t = hi; 01494 if ((*funcp)(&t, offset, &mytm, sp) == NULL) { 01495 /* 01496 ** Assume that t is too extreme to be represented in 01497 ** a struct tm; arrange things so that it is less 01498 ** extreme on the next pass. 01499 */ 01500 dir = (t > 0) ? 1 : -1; 01501 } else dir = tmcomp(&mytm, &yourtm); 01502 if (dir != 0) { 01503 if (t == lo) { 01504 ++t; 01505 if (t <= lo) 01506 return WRONG; 01507 ++lo; 01508 } else if (t == hi) { 01509 --t; 01510 if (t >= hi) 01511 return WRONG; 01512 --hi; 01513 } 01514 if (lo > hi) 01515 return WRONG; 01516 if (dir > 0) 01517 hi = t; 01518 else lo = t; 01519 continue; 01520 } 01521 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 01522 break; 01523 /* 01524 ** Right time, wrong type. 01525 ** Hunt for right time, right type. 01526 ** It's okay to guess wrong since the guess 01527 ** gets checked. 01528 */ 01529 /* 01530 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 01531 */ 01532 for (i = sp->typecnt - 1; i >= 0; --i) { 01533 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 01534 continue; 01535 for (j = sp->typecnt - 1; j >= 0; --j) { 01536 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 01537 continue; 01538 newt = t + sp->ttis[j].tt_gmtoff - 01539 sp->ttis[i].tt_gmtoff; 01540 if ((*funcp)(&newt, offset, &mytm, sp) == NULL) 01541 continue; 01542 if (tmcomp(&mytm, &yourtm) != 0) 01543 continue; 01544 if (mytm.tm_isdst != yourtm.tm_isdst) 01545 continue; 01546 /* 01547 ** We have a match. 01548 */ 01549 t = newt; 01550 goto label; 01551 } 01552 } 01553 return WRONG; 01554 } 01555 label: 01556 newt = t + saved_seconds; 01557 if ((newt < t) != (saved_seconds < 0)) 01558 return WRONG; 01559 t = newt; 01560 if ((*funcp)(&t, offset, tmp, sp)) 01561 *okayp = TRUE; 01562 return t; 01563 }
static struct tm* timesub | ( | const time_t * | timep, | |
const long | offset, | |||
const struct state * | sp, | |||
struct tm * | tmp | |||
) | [static, read] |
Definition at line 1201 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().
01202 { 01203 const struct lsinfo * lp; 01204 time_t tdays; 01205 int idays; /* unsigned would be so 2003 */ 01206 long rem; 01207 int y; 01208 const int * ip; 01209 long corr; 01210 int hit; 01211 int i; 01212 long seconds; 01213 01214 01215 corr = 0; 01216 hit = 0; 01217 i = (sp == NULL) ? 0 : sp->leapcnt; 01218 while (--i >= 0) { 01219 lp = &sp->lsis[i]; 01220 if (*timep >= lp->ls_trans) { 01221 if (*timep == lp->ls_trans) { 01222 hit = ((i == 0 && lp->ls_corr > 0) || 01223 lp->ls_corr > sp->lsis[i - 1].ls_corr); 01224 if (hit) 01225 while (i > 0 && 01226 sp->lsis[i].ls_trans == 01227 sp->lsis[i - 1].ls_trans + 1 && 01228 sp->lsis[i].ls_corr == 01229 sp->lsis[i - 1].ls_corr + 1) { 01230 ++hit; 01231 --i; 01232 } 01233 } 01234 corr = lp->ls_corr; 01235 break; 01236 } 01237 } 01238 y = EPOCH_YEAR; 01239 tdays = *timep / SECSPERDAY; 01240 rem = *timep - tdays * SECSPERDAY; 01241 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 01242 int newy; 01243 time_t tdelta; 01244 int idelta; 01245 int leapdays; 01246 01247 tdelta = tdays / DAYSPERLYEAR; 01248 idelta = tdelta; 01249 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 01250 return NULL; 01251 if (idelta == 0) 01252 idelta = (tdays < 0) ? -1 : 1; 01253 newy = y; 01254 if (increment_overflow(&newy, idelta)) 01255 return NULL; 01256 leapdays = leaps_thru_end_of(newy - 1) - 01257 leaps_thru_end_of(y - 1); 01258 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 01259 tdays -= leapdays; 01260 y = newy; 01261 } 01262 01263 seconds = tdays * SECSPERDAY + 0.5; 01264 tdays = seconds / SECSPERDAY; 01265 rem += seconds - tdays * SECSPERDAY; 01266 01267 /* 01268 ** Given the range, we can now fearlessly cast... 01269 */ 01270 idays = tdays; 01271 rem += offset - corr; 01272 while (rem < 0) { 01273 rem += SECSPERDAY; 01274 --idays; 01275 } 01276 while (rem >= SECSPERDAY) { 01277 rem -= SECSPERDAY; 01278 ++idays; 01279 } 01280 while (idays < 0) { 01281 if (increment_overflow(&y, -1)) 01282 return NULL; 01283 idays += year_lengths[isleap(y)]; 01284 } 01285 while (idays >= year_lengths[isleap(y)]) { 01286 idays -= year_lengths[isleap(y)]; 01287 if (increment_overflow(&y, 1)) 01288 return NULL; 01289 } 01290 tmp->tm_year = y; 01291 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 01292 return NULL; 01293 tmp->tm_yday = idays; 01294 /* 01295 ** The "extra" mods below avoid overflow problems. 01296 */ 01297 tmp->tm_wday = EPOCH_WDAY + 01298 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 01299 (DAYSPERNYEAR % DAYSPERWEEK) + 01300 leaps_thru_end_of(y - 1) - 01301 leaps_thru_end_of(EPOCH_YEAR - 1) + 01302 idays; 01303 tmp->tm_wday %= DAYSPERWEEK; 01304 if (tmp->tm_wday < 0) 01305 tmp->tm_wday += DAYSPERWEEK; 01306 tmp->tm_hour = (int) (rem / SECSPERHOUR); 01307 rem %= SECSPERHOUR; 01308 tmp->tm_min = (int) (rem / SECSPERMIN); 01309 /* 01310 ** A positive leap second requires a special 01311 ** representation. This uses "... ??:59:60" et seq. 01312 */ 01313 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 01314 ip = mon_lengths[isleap(y)]; 01315 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 01316 idays -= ip[tmp->tm_mon]; 01317 tmp->tm_mday = (int) (idays + 1); 01318 tmp->tm_isdst = 0; 01319 #ifdef TM_GMTOFF 01320 tmp->TM_GMTOFF = offset; 01321 #endif /* defined TM_GMTOFF */ 01322 return tmp; 01323 }
static int tmcomp | ( | const struct tm * | atmp, | |
const struct tm * | btmp | |||
) | [static] |
Definition at line 1378 of file localtime.c.
Referenced by time2sub().
01379 { 01380 int result; 01381 01382 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 01383 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 01384 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 01385 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 01386 (result = (atmp->tm_min - btmp->tm_min)) == 0) 01387 result = atmp->tm_sec - btmp->tm_sec; 01388 return result; 01389 }
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().