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