#include "asterisk.h"
#include <signal.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" |
Functions | |
void | ast_get_dst_info (const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone) |
ast_tm * | ast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone) |
timeval | ast_mktime (struct ast_tm *tmp, const char *zone) |
int | ast_strftime (char *buf, size_t len, const char *tmp, const struct ast_tm *tm) |
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 ast_tm * | gmtsub (const struct timeval *timep, const long offset, struct ast_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 ast_tm * | localsub (const struct timeval *timep, const long offset, struct ast_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 ast_tm *atmp, const struct ast_tm *btmp)) |
static struct ast_tm *timesub | P ((const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp)) |
static struct timeval time2sub | P ((struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp)) |
static struct timeval time2 | P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp)) |
static struct timeval time1 | P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_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 ast_tm *localsub | P ((const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp)) |
static struct ast_tm *gmtsub | P ((const struct timeval *timep, long offset, struct ast_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 struct timeval | time1 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp) |
static struct timeval | time2 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp) |
static struct timeval | time2sub (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp) |
static struct ast_tm * | timesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp) |
static int | tmcomp (const struct ast_tm *atmp, const struct ast_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 struct timeval | WRONG = { 0, 0 } |
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 124 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 130 of file localtime.c.
#define OPEN_MODE O_RDONLY |
#define TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
Definition at line 76 of file localtime.c.
#define TZ_ABBR_ERR_CHAR '_' |
Definition at line 81 of file localtime.c.
#define TZ_ABBR_MAX_LEN 16 |
Definition at line 72 of file localtime.c.
#define TZ_STRLEN_MAX 255 |
Definition at line 133 of file localtime.c.
#define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Definition at line 106 of file localtime.c.
Referenced by tzparse().
void ast_get_dst_info | ( | const time_t *const | timep, | |
int * | dst_enabled, | |||
time_t * | dst_start, | |||
time_t * | dst_end, | |||
int * | gmt_off, | |||
const char *const | zone | |||
) |
Definition at line 1156 of file localtime.c.
References ast_tzset(), state::ats, AVGSECSPERYEAR, state::goahead, state::goback, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.
Referenced by set_timezone_variables().
01157 { 01158 int i; 01159 int transition1 = -1; 01160 int transition2 = -1; 01161 time_t seconds; 01162 int bounds_exceeded = 0; 01163 time_t t = *timep; 01164 const struct state *sp; 01165 01166 if (NULL == dst_enabled) 01167 return; 01168 *dst_enabled = 0; 01169 01170 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off) 01171 return; 01172 01173 *gmt_off = 0; 01174 01175 sp = ast_tzset(zone); 01176 if (NULL == sp) 01177 return; 01178 01179 /* If the desired time exceeds the bounds of the defined time transitions 01180 * then give give up on determining DST info and simply look for gmt offset 01181 * This requires that I adjust the given time using increments of Gregorian 01182 * repeats to place the time within the defined time transitions in the 01183 * timezone structure. 01184 */ 01185 if ((sp->goback && t < sp->ats[0]) || 01186 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 01187 time_t tcycles; 01188 int_fast64_t icycles; 01189 01190 if (t < sp->ats[0]) 01191 seconds = sp->ats[0] - t; 01192 else seconds = t - sp->ats[sp->timecnt - 1]; 01193 --seconds; 01194 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01195 ++tcycles; 01196 icycles = tcycles; 01197 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01198 return; 01199 seconds = icycles; 01200 seconds *= YEARSPERREPEAT; 01201 seconds *= AVGSECSPERYEAR; 01202 if (t < sp->ats[0]) 01203 t += seconds; 01204 else 01205 t -= seconds; 01206 01207 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1]) 01208 return; /* "cannot happen" */ 01209 01210 bounds_exceeded = 1; 01211 } 01212 01213 if (sp->timecnt == 0 || t < sp->ats[0]) { 01214 /* I have no transition times or I'm before time */ 01215 *dst_enabled = 0; 01216 /* Find where I can get gmtoff */ 01217 i = 0; 01218 while (sp->ttis[i].tt_isdst) 01219 if (++i >= sp->typecnt) { 01220 i = 0; 01221 break; 01222 } 01223 *gmt_off = sp->ttis[i].tt_gmtoff; 01224 return; 01225 } 01226 01227 for (i = 1; i < sp->timecnt; ++i) { 01228 if (t < sp->ats[i]) { 01229 transition1 = sp->types[i - 1]; 01230 transition2 = sp->types[i]; 01231 break; 01232 } 01233 } 01234 /* if I found transition times that do not bounded the given time and these correspond to 01235 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */ 01236 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 || 01237 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) { 01238 *dst_enabled = 0; 01239 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff; 01240 } else { 01241 /* I have valid daylight savings information. */ 01242 if(sp->ttis[transition2].tt_isdst) 01243 *gmt_off = sp->ttis[transition1].tt_gmtoff; 01244 else 01245 *gmt_off = sp->ttis[transition2].tt_gmtoff; 01246 01247 /* If I adjusted the time earlier, indicate that the dst is invalid */ 01248 if (!bounds_exceeded) { 01249 *dst_enabled = 1; 01250 /* Determine which of the bounds is the start of daylight savings and which is the end */ 01251 if(sp->ttis[transition2].tt_isdst) { 01252 *dst_start = sp->ats[i]; 01253 *dst_end = sp->ats[i -1]; 01254 } else { 01255 *dst_start = sp->ats[i -1]; 01256 *dst_end = sp->ats[i]; 01257 } 01258 } 01259 } 01260 return; 01261 }
struct ast_tm* ast_localtime | ( | const struct timeval * | timep, | |
struct ast_tm * | tmp, | |||
const char * | zone | |||
) |
Definition at line 1141 of file localtime.c.
References ast_tzset(), and localsub().
Referenced by __ast_verbose_ap(), 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_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_th(), 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_th(), 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_hu(), ast_say_datetime_ka(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_th(), ast_say_time_zh(), build_device(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), enc_ie_date(), execute_cb(), find_conf_realtime(), get_date(), handle_minivm_show_stats(), handle_show_settings(), handle_time_date_req_message(), httpd_helper_thread(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), manager_log(), packdate(), pgsql_log(), phone_call(), phoneprov_callback(), play_message_datetime(), prep_email_sub_vars(), rpt_localtime(), say_date_generic(), send_date_time(), send_date_time2(), send_date_time3(), sendmail(), set_timezone_variables(), sip_show_registry(), sms_compose2(), sms_handleincoming_proto2(), sqlite_log(), static_callback(), timeout_write(), transmit_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().
01142 { 01143 const struct state *sp = ast_tzset(zone); 01144 memset(tmp, 0, sizeof(*tmp)); 01145 return sp ? localsub(timep, 0L, tmp, sp) : NULL; 01146 }
struct timeval ast_mktime | ( | struct ast_tm * | tmp, | |
const char * | zone | |||
) |
Definition at line 1756 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime(), find_conf_realtime(), sms_handleincoming_proto2(), sms_readfile(), and unpackdate().
01757 { 01758 const struct state *sp; 01759 if (!(sp = ast_tzset(zone))) 01760 return WRONG; 01761 return time1(tmp, localsub, 0L, sp); 01762 }
int ast_strftime | ( | char * | buf, | |
size_t | len, | |||
const char * | tmp, | |||
const struct ast_tm * | tm | |||
) |
Definition at line 1764 of file localtime.c.
References ast_calloc, ast_free, ast_realloc, format, and ast_tm::tm_usec.
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), dump_datetime(), execute_cb(), find_conf_realtime(), get_date(), handle_minivm_show_stats(), handle_show_settings(), httpd_helper_thread(), isodate(), leave_voicemail(), make_email_file(), manager_log(), pgsql_log(), phoneprov_callback(), prep_email_sub_vars(), sendmail(), sendpage(), sip_show_registry(), sqlite_log(), static_callback(), timeout_write(), and write_metadata().
01765 { 01766 size_t fmtlen = strlen(tmp) + 1; 01767 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt; 01768 int decimals = -1, i, res; 01769 long fraction; 01770 01771 if (!format) 01772 return -1; 01773 for (; *tmp; tmp++) { 01774 if (*tmp == '%') { 01775 switch (tmp[1]) { 01776 case '1': 01777 case '2': 01778 case '3': 01779 case '4': 01780 case '5': 01781 case '6': 01782 if (tmp[2] != 'q') 01783 goto defcase; 01784 decimals = tmp[1] - '0'; 01785 tmp++; 01786 /* Fall through */ 01787 case 'q': /* Milliseconds */ 01788 if (decimals == -1) 01789 decimals = 3; 01790 01791 /* Juggle some memory to fit the item */ 01792 newfmt = ast_realloc(format, fmtlen + decimals); 01793 if (!newfmt) { 01794 ast_free(format); 01795 return -1; 01796 } 01797 fptr = fptr - format + newfmt; 01798 format = newfmt; 01799 fmtlen += decimals; 01800 01801 /* Reduce the fraction of time to the accuracy needed */ 01802 for (i = 6, fraction = tm->tm_usec; i > decimals; i--) 01803 fraction /= 10; 01804 fptr += sprintf(fptr, "%0*ld", decimals, fraction); 01805 01806 /* Reset, in case more than one 'q' specifier exists */ 01807 decimals = -1; 01808 tmp++; 01809 break; 01810 default: 01811 goto defcase; 01812 } 01813 } else 01814 defcase: *fptr++ = *tmp; 01815 } 01816 *fptr = '\0'; 01817 #undef strftime 01818 res = (int)strftime(buf, len, format, (struct tm *)tm); 01819 ast_free(format); 01820 return res; 01821 }
static struct state* ast_tzset | ( | const char * | zone | ) | [static] |
Definition at line 1011 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_get_dst_info(), ast_localtime(), and ast_mktime().
01012 { 01013 struct state *sp; 01014 01015 if (ast_strlen_zero(zone)) 01016 zone = "/etc/localtime"; 01017 01018 AST_LIST_LOCK(&zonelist); 01019 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01020 if (!strcmp(sp->name, zone)) { 01021 AST_LIST_UNLOCK(&zonelist); 01022 return sp; 01023 } 01024 } 01025 AST_LIST_UNLOCK(&zonelist); 01026 01027 if (!(sp = ast_calloc(1, sizeof *sp))) 01028 return NULL; 01029 01030 if (tzload(zone, sp, TRUE) != 0) { 01031 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0) 01032 (void) gmtload(sp); 01033 } 01034 ast_copy_string(sp->name, zone, sizeof(sp->name)); 01035 AST_LIST_LOCK(&zonelist); 01036 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01037 AST_LIST_UNLOCK(&zonelist); 01038 return sp; 01039 }
static long detzcode | ( | const char *const | codep | ) | [static] |
Definition at line 229 of file localtime.c.
Referenced by tzload().
00230 { 00231 long result; 00232 int i; 00233 00234 result = (codep[0] & 0x80) ? ~0L : 0; 00235 for (i = 0; i < 4; ++i) 00236 result = (result << 8) | (codep[i] & 0xff); 00237 return result; 00238 }
static time_t detzcode64 | ( | const char *const | codep | ) | [static] |
Definition at line 240 of file localtime.c.
Referenced by tzload().
00241 { 00242 time_t result; 00243 int i; 00244 00245 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 00246 for (i = 0; i < 8; ++i) 00247 result = result * 256 + (codep[i] & 0xff); 00248 return result; 00249 }
static int differ_by_repeat | ( | const time_t | t1, | |
const time_t | t0 | |||
) | [static] |
Definition at line 251 of file localtime.c.
References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.
00252 { 00253 const long long at1 = t1, at0 = t0; 00254 if (TYPE_INTEGRAL(time_t) && 00255 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) 00256 return 0; 00257 return at1 - at0 == SECSPERREPEAT; 00258 }
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 540 of file localtime.c.
Referenced by getrule(), and getsecs().
00541 { 00542 char c; 00543 int num; 00544 00545 if (strp == NULL || !is_digit(c = *strp)) 00546 return NULL; 00547 num = 0; 00548 do { 00549 num = num * 10 + (c - '0'); 00550 if (num > max) 00551 return NULL; /* illegal value */ 00552 c = *++strp; 00553 } while (is_digit(c)); 00554 if (num < min) 00555 return NULL; /* illegal value */ 00556 *nump = num; 00557 return strp; 00558 }
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 607 of file localtime.c.
References getsecs().
Referenced by tzparse().
00608 { 00609 int neg = 0; 00610 00611 if (*strp == '-') { 00612 neg = 1; 00613 ++strp; 00614 } else if (*strp == '+') 00615 ++strp; 00616 strp = getsecs(strp, offsetp); 00617 if (strp == NULL) 00618 return NULL; /* illegal time */ 00619 if (neg) 00620 *offsetp = -*offsetp; 00621 return strp; 00622 }
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 524 of file localtime.c.
Referenced by tzparse().
00525 { 00526 int c; 00527 00528 while ((c = *strp) != '\0' && c != delim) 00529 ++strp; 00530 return strp; 00531 }
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 631 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().
00632 { 00633 if (*strp == 'J') { 00634 /* 00635 ** Julian day. 00636 */ 00637 rulep->r_type = JULIAN_DAY; 00638 ++strp; 00639 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 00640 } else if (*strp == 'M') { 00641 /* 00642 ** Month, week, day. 00643 */ 00644 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 00645 ++strp; 00646 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 00647 if (strp == NULL) 00648 return NULL; 00649 if (*strp++ != '.') 00650 return NULL; 00651 strp = getnum(strp, &rulep->r_week, 1, 5); 00652 if (strp == NULL) 00653 return NULL; 00654 if (*strp++ != '.') 00655 return NULL; 00656 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 00657 } else if (is_digit(*strp)) { 00658 /* 00659 ** Day of year. 00660 */ 00661 rulep->r_type = DAY_OF_YEAR; 00662 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 00663 } else return NULL; /* invalid format */ 00664 if (strp == NULL) 00665 return NULL; 00666 if (*strp == '/') { 00667 /* 00668 ** Time specified. 00669 */ 00670 ++strp; 00671 strp = getsecs(strp, &rulep->r_time); 00672 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 00673 return strp; 00674 }
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 568 of file localtime.c.
References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, num, SECSPERHOUR, and SECSPERMIN.
Referenced by getoffset(), and getrule().
00569 { 00570 int num; 00571 00572 /* 00573 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 00574 ** "M10.4.6/26", which does not conform to Posix, 00575 ** but which specifies the equivalent of 00576 ** ``02:00 on the first Sunday on or after 23 Oct''. 00577 */ 00578 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 00579 if (strp == NULL) 00580 return NULL; 00581 *secsp = num * (long) SECSPERHOUR; 00582 if (*strp == ':') { 00583 ++strp; 00584 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 00585 if (strp == NULL) 00586 return NULL; 00587 *secsp += num * SECSPERMIN; 00588 if (*strp == ':') { 00589 ++strp; 00590 /* `SECSPERMIN' allows for leap seconds. */ 00591 strp = getnum(strp, &num, 0, SECSPERMIN); 00592 if (strp == NULL) 00593 return NULL; 00594 *secsp += num; 00595 } 00596 } 00597 return strp; 00598 }
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 505 of file localtime.c.
References is_digit.
Referenced by tzparse().
00506 { 00507 char c; 00508 00509 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 00510 c != '+') 00511 ++strp; 00512 return strp; 00513 }
static int gmtload | ( | struct state * | sp | ) | [static] |
static struct ast_tm* gmtsub | ( | const struct timeval * | timep, | |
const long | offset, | |||
struct ast_tm * | tmp | |||
) | [static] |
Definition at line 1267 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().
01268 { 01269 struct ast_tm * result; 01270 struct state *sp; 01271 01272 AST_LIST_LOCK(&zonelist); 01273 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01274 if (!strcmp(sp->name, "UTC")) 01275 break; 01276 } 01277 01278 if (!sp) { 01279 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp))) 01280 return NULL; 01281 gmtload(sp); 01282 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01283 } 01284 AST_LIST_UNLOCK(&zonelist); 01285 01286 result = timesub(timep, offset, sp, tmp); 01287 #ifdef TM_ZONE 01288 /* 01289 ** Could get fancy here and deliver something such as 01290 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 01291 ** but this is no time for a treasure hunt. 01292 */ 01293 if (offset != 0) 01294 tmp->TM_ZONE = " "; 01295 else 01296 tmp->TM_ZONE = sp->chars; 01297 #endif /* defined TM_ZONE */ 01298 return result; 01299 }
static int increment_overflow | ( | int * | number, | |
int | delta | |||
) | [static] |
Simplified normalize logic courtesy Paul Eggert.
Definition at line 1450 of file localtime.c.
Referenced by normalize_overflow(), and timesub().
01451 { 01452 int number0; 01453 01454 number0 = *number; 01455 *number += delta; 01456 return (*number < number0) != (delta < 0); 01457 }
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 1306 of file localtime.c.
Referenced by timesub().
01307 { 01308 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 01309 -(leaps_thru_end_of(-(y + 1)) + 1); 01310 }
static struct ast_tm* localsub | ( | const struct timeval * | timep, | |
const long | offset, | |||
struct ast_tm * | tmp, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1050 of file localtime.c.
References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, state::timecnt, timesub(), ast_tm::tm_gmtoff, ast_tm::tm_isdst, ast_tm::tm_usec, ast_tm::tm_year, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.
Referenced by ast_localtime(), and ast_mktime().
01051 { 01052 const struct ttinfo * ttisp; 01053 int i; 01054 struct ast_tm * result; 01055 struct timeval t; 01056 memcpy(&t, timep, sizeof(t)); 01057 01058 if (sp == NULL) 01059 return gmtsub(timep, offset, tmp); 01060 if ((sp->goback && t.tv_sec < sp->ats[0]) || 01061 (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) { 01062 struct timeval newt = t; 01063 time_t seconds; 01064 time_t tcycles; 01065 int_fast64_t icycles; 01066 01067 if (t.tv_sec < sp->ats[0]) 01068 seconds = sp->ats[0] - t.tv_sec; 01069 else seconds = t.tv_sec - sp->ats[sp->timecnt - 1]; 01070 --seconds; 01071 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01072 ++tcycles; 01073 icycles = tcycles; 01074 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01075 return NULL; 01076 seconds = icycles; 01077 seconds *= YEARSPERREPEAT; 01078 seconds *= AVGSECSPERYEAR; 01079 if (t.tv_sec < sp->ats[0]) 01080 newt.tv_sec += seconds; 01081 else newt.tv_sec -= seconds; 01082 if (newt.tv_sec < sp->ats[0] || 01083 newt.tv_sec > sp->ats[sp->timecnt - 1]) 01084 return NULL; /* "cannot happen" */ 01085 result = localsub(&newt, offset, tmp, sp); 01086 if (result == tmp) { 01087 time_t newy; 01088 01089 newy = tmp->tm_year; 01090 if (t.tv_sec < sp->ats[0]) 01091 newy -= icycles * YEARSPERREPEAT; 01092 else 01093 newy += icycles * YEARSPERREPEAT; 01094 tmp->tm_year = newy; 01095 if (tmp->tm_year != newy) 01096 return NULL; 01097 } 01098 return result; 01099 } 01100 if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) { 01101 i = 0; 01102 while (sp->ttis[i].tt_isdst) { 01103 if (++i >= sp->typecnt) { 01104 i = 0; 01105 break; 01106 } 01107 } 01108 } else { 01109 int lo = 1; 01110 int hi = sp->timecnt; 01111 01112 while (lo < hi) { 01113 int mid = (lo + hi) >> 1; 01114 01115 if (t.tv_sec < sp->ats[mid]) 01116 hi = mid; 01117 else 01118 lo = mid + 1; 01119 } 01120 i = (int) sp->types[lo - 1]; 01121 } 01122 ttisp = &sp->ttis[i]; 01123 /* 01124 ** To get (wrong) behavior that's compatible with System V Release 2.0 01125 ** you'd replace the statement below with 01126 ** t += ttisp->tt_gmtoff; 01127 ** timesub(&t, 0L, sp, tmp); 01128 */ 01129 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 01130 tmp->tm_isdst = ttisp->tt_isdst; 01131 #ifndef SOLARIS /* Solaris doesn't have this element */ 01132 tmp->tm_gmtoff = ttisp->tt_gmtoff; 01133 #endif 01134 #ifdef TM_ZONE 01135 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 01136 #endif /* defined TM_ZONE */ 01137 tmp->tm_usec = timep->tv_usec; 01138 return result; 01139 }
static int long_increment_overflow | ( | long * | number, | |
int | delta | |||
) | [static] |
Definition at line 1459 of file localtime.c.
Referenced by long_normalize_overflow(), and time2sub().
01460 { 01461 long number0; 01462 01463 number0 = *number; 01464 *number += delta; 01465 return (*number < number0) != (delta < 0); 01466 }
static int long_normalize_overflow | ( | long * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1479 of file localtime.c.
References long_increment_overflow().
Referenced by time2sub().
01480 { 01481 int tensdelta; 01482 01483 tensdelta = (*unitsptr >= 0) ? 01484 (*unitsptr / base) : 01485 (-1 - (-1 - *unitsptr) / base); 01486 *unitsptr -= tensdelta * base; 01487 return long_increment_overflow(tensptr, tensdelta); 01488 }
static int normalize_overflow | ( | int * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1468 of file localtime.c.
References increment_overflow().
Referenced by time2sub().
01469 { 01470 int tensdelta; 01471 01472 tensdelta = (*unitsptr >= 0) ? 01473 (*unitsptr / base) : 01474 (-1 - (-1 - *unitsptr) / base); 01475 *unitsptr -= tensdelta * base; 01476 return increment_overflow(tensptr, tensdelta); 01477 }
static time_t transtime P | ( | (time_t janfirst, int year, const struct rule *rulep, long offset) | ) | [static] |
static struct ast_tm* timesub P | ( | (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp) | ) | [static] |
static struct timeval time2sub P | ( | (struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp) | ) | [static] |
static struct timeval time2 P | ( | (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp) | ) | [static] |
static struct timeval time1 P | ( | (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_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 ast_tm* localsub P | ( | (const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp) | ) | [static] |
static struct ast_tm* gmtsub P | ( | (const struct timeval *timep, long offset, struct ast_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 struct timeval time1 | ( | struct ast_tm * | tmp, | |
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *) | funcp, | |||
const long | offset, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1691 of file localtime.c.
References FALSE, time2(), state::timecnt, TRUE, state::typecnt, state::types, and TZ_MAX_TYPES.
Referenced by ast_mktime().
01692 { 01693 struct timeval t; 01694 int samei, otheri; 01695 int sameind, otherind; 01696 int i; 01697 int nseen; 01698 int seen[TZ_MAX_TYPES]; 01699 int types[TZ_MAX_TYPES]; 01700 int okay; 01701 01702 if (tmp->tm_isdst > 1) 01703 tmp->tm_isdst = 1; 01704 t = time2(tmp, funcp, offset, &okay, sp); 01705 #ifdef PCTS 01706 /* 01707 ** PCTS code courtesy Grant Sullivan. 01708 */ 01709 if (okay) 01710 return t; 01711 if (tmp->tm_isdst < 0) 01712 tmp->tm_isdst = 0; /* reset to std and try again */ 01713 #endif /* defined PCTS */ 01714 #ifndef PCTS 01715 if (okay || tmp->tm_isdst < 0) 01716 return t; 01717 #endif /* !defined PCTS */ 01718 /* 01719 ** We're supposed to assume that somebody took a time of one type 01720 ** and did some math on it that yielded a "struct ast_tm" that's bad. 01721 ** We try to divine the type they started from and adjust to the 01722 ** type they need. 01723 */ 01724 if (sp == NULL) 01725 return WRONG; 01726 for (i = 0; i < sp->typecnt; ++i) 01727 seen[i] = FALSE; 01728 nseen = 0; 01729 for (i = sp->timecnt - 1; i >= 0; --i) 01730 if (!seen[sp->types[i]]) { 01731 seen[sp->types[i]] = TRUE; 01732 types[nseen++] = sp->types[i]; 01733 } 01734 for (sameind = 0; sameind < nseen; ++sameind) { 01735 samei = types[sameind]; 01736 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 01737 continue; 01738 for (otherind = 0; otherind < nseen; ++otherind) { 01739 otheri = types[otherind]; 01740 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 01741 continue; 01742 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 01743 sp->ttis[samei].tt_gmtoff; 01744 tmp->tm_isdst = !tmp->tm_isdst; 01745 t = time2(tmp, funcp, offset, &okay, sp); 01746 if (okay) 01747 return t; 01748 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 01749 sp->ttis[samei].tt_gmtoff; 01750 tmp->tm_isdst = !tmp->tm_isdst; 01751 } 01752 } 01753 return WRONG; 01754 }
static struct timeval time2 | ( | struct ast_tm * | tmp, | |
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *sp) | funcp, | |||
const long | offset, | |||
int * | okayp, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1678 of file localtime.c.
References FALSE, time2sub(), and TRUE.
Referenced by time1().
01679 { 01680 struct timeval t; 01681 01682 /*! \note 01683 ** First try without normalization of seconds 01684 ** (in case tm_sec contains a value associated with a leap second). 01685 ** If that fails, try with normalization of seconds. 01686 */ 01687 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); 01688 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); 01689 }
static struct timeval time2sub | ( | struct ast_tm * | tmp, | |
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *) | funcp, | |||
const long | offset, | |||
int * | okayp, | |||
const int | do_norm_secs, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1504 of file localtime.c.
References DAYSPERLYEAR, dir, FALSE, HOURSPERDAY, isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, and year_lengths.
Referenced by time2().
01505 { 01506 int dir; 01507 int i, j; 01508 int saved_seconds; 01509 long li; 01510 time_t lo; 01511 time_t hi; 01512 long y; 01513 struct timeval newt = { 0, 0 }; 01514 struct timeval t = { 0, 0 }; 01515 struct ast_tm yourtm, mytm; 01516 01517 *okayp = FALSE; 01518 yourtm = *tmp; 01519 if (do_norm_secs) { 01520 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 01521 SECSPERMIN)) 01522 return WRONG; 01523 } 01524 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 01525 return WRONG; 01526 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 01527 return WRONG; 01528 y = yourtm.tm_year; 01529 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 01530 return WRONG; 01531 /* 01532 ** Turn y into an actual year number for now. 01533 ** It is converted back to an offset from TM_YEAR_BASE later. 01534 */ 01535 if (long_increment_overflow(&y, TM_YEAR_BASE)) 01536 return WRONG; 01537 while (yourtm.tm_mday <= 0) { 01538 if (long_increment_overflow(&y, -1)) 01539 return WRONG; 01540 li = y + (1 < yourtm.tm_mon); 01541 yourtm.tm_mday += year_lengths[isleap(li)]; 01542 } 01543 while (yourtm.tm_mday > DAYSPERLYEAR) { 01544 li = y + (1 < yourtm.tm_mon); 01545 yourtm.tm_mday -= year_lengths[isleap(li)]; 01546 if (long_increment_overflow(&y, 1)) 01547 return WRONG; 01548 } 01549 for ( ; ; ) { 01550 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 01551 if (yourtm.tm_mday <= i) 01552 break; 01553 yourtm.tm_mday -= i; 01554 if (++yourtm.tm_mon >= MONSPERYEAR) { 01555 yourtm.tm_mon = 0; 01556 if (long_increment_overflow(&y, 1)) 01557 return WRONG; 01558 } 01559 } 01560 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 01561 return WRONG; 01562 yourtm.tm_year = y; 01563 if (yourtm.tm_year != y) 01564 return WRONG; 01565 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 01566 saved_seconds = 0; 01567 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 01568 /* 01569 ** We can't set tm_sec to 0, because that might push the 01570 ** time below the minimum representable time. 01571 ** Set tm_sec to 59 instead. 01572 ** This assumes that the minimum representable time is 01573 ** not in the same minute that a leap second was deleted from, 01574 ** which is a safer assumption than using 58 would be. 01575 */ 01576 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 01577 return WRONG; 01578 saved_seconds = yourtm.tm_sec; 01579 yourtm.tm_sec = SECSPERMIN - 1; 01580 } else { 01581 saved_seconds = yourtm.tm_sec; 01582 yourtm.tm_sec = 0; 01583 } 01584 /* 01585 ** Do a binary search (this works whatever time_t's type is). 01586 */ 01587 if (!TYPE_SIGNED(time_t)) { 01588 lo = 0; 01589 hi = lo - 1; 01590 } else if (!TYPE_INTEGRAL(time_t)) { 01591 if (sizeof(time_t) > sizeof(float)) 01592 hi = (time_t) DBL_MAX; 01593 else hi = (time_t) FLT_MAX; 01594 lo = -hi; 01595 } else { 01596 lo = 1; 01597 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 01598 lo *= 2; 01599 hi = -(lo + 1); 01600 } 01601 for ( ; ; ) { 01602 t.tv_sec = lo / 2 + hi / 2; 01603 if (t.tv_sec < lo) 01604 t.tv_sec = lo; 01605 else if (t.tv_sec > hi) 01606 t.tv_sec = hi; 01607 if ((*funcp)(&t, offset, &mytm, sp) == NULL) { 01608 /* 01609 ** Assume that t is too extreme to be represented in 01610 ** a struct ast_tm; arrange things so that it is less 01611 ** extreme on the next pass. 01612 */ 01613 dir = (t.tv_sec > 0) ? 1 : -1; 01614 } else dir = tmcomp(&mytm, &yourtm); 01615 if (dir != 0) { 01616 if (t.tv_sec == lo) { 01617 ++t.tv_sec; 01618 if (t.tv_sec <= lo) 01619 return WRONG; 01620 ++lo; 01621 } else if (t.tv_sec == hi) { 01622 --t.tv_sec; 01623 if (t.tv_sec >= hi) 01624 return WRONG; 01625 --hi; 01626 } 01627 if (lo > hi) 01628 return WRONG; 01629 if (dir > 0) 01630 hi = t.tv_sec; 01631 else lo = t.tv_sec; 01632 continue; 01633 } 01634 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 01635 break; 01636 /* 01637 ** Right time, wrong type. 01638 ** Hunt for right time, right type. 01639 ** It's okay to guess wrong since the guess 01640 ** gets checked. 01641 */ 01642 /* 01643 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 01644 */ 01645 for (i = sp->typecnt - 1; i >= 0; --i) { 01646 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 01647 continue; 01648 for (j = sp->typecnt - 1; j >= 0; --j) { 01649 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 01650 continue; 01651 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff - 01652 sp->ttis[i].tt_gmtoff; 01653 if ((*funcp)(&newt, offset, &mytm, sp) == NULL) 01654 continue; 01655 if (tmcomp(&mytm, &yourtm) != 0) 01656 continue; 01657 if (mytm.tm_isdst != yourtm.tm_isdst) 01658 continue; 01659 /* 01660 ** We have a match. 01661 */ 01662 t = newt; 01663 goto label; 01664 } 01665 } 01666 return WRONG; 01667 } 01668 label: 01669 newt.tv_sec = t.tv_sec + saved_seconds; 01670 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0)) 01671 return WRONG; 01672 t.tv_sec = newt.tv_sec; 01673 if ((*funcp)(&t, offset, tmp, sp)) 01674 *okayp = TRUE; 01675 return t; 01676 }
static struct ast_tm* timesub | ( | const struct timeval * | timep, | |
const long | offset, | |||
const struct state * | sp, | |||
struct ast_tm * | tmp | |||
) | [static] |
Definition at line 1312 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, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_yday, ast_tm::tm_year, TM_YEAR_BASE, and year_lengths.
Referenced by gmtsub(), and localsub().
01313 { 01314 const struct lsinfo * lp; 01315 time_t tdays; 01316 int idays; /* unsigned would be so 2003 */ 01317 long rem; 01318 int y; 01319 const int * ip; 01320 long corr; 01321 int hit; 01322 int i; 01323 long seconds; 01324 01325 01326 corr = 0; 01327 hit = 0; 01328 i = (sp == NULL) ? 0 : sp->leapcnt; 01329 while (--i >= 0) { 01330 lp = &sp->lsis[i]; 01331 if (timep->tv_sec >= lp->ls_trans) { 01332 if (timep->tv_sec == lp->ls_trans) { 01333 hit = ((i == 0 && lp->ls_corr > 0) || 01334 lp->ls_corr > sp->lsis[i - 1].ls_corr); 01335 if (hit) 01336 while (i > 0 && 01337 sp->lsis[i].ls_trans == 01338 sp->lsis[i - 1].ls_trans + 1 && 01339 sp->lsis[i].ls_corr == 01340 sp->lsis[i - 1].ls_corr + 1) { 01341 ++hit; 01342 --i; 01343 } 01344 } 01345 corr = lp->ls_corr; 01346 break; 01347 } 01348 } 01349 y = EPOCH_YEAR; 01350 tdays = timep->tv_sec / SECSPERDAY; 01351 rem = timep->tv_sec - tdays * SECSPERDAY; 01352 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 01353 int newy; 01354 time_t tdelta; 01355 int idelta; 01356 int leapdays; 01357 01358 tdelta = tdays / DAYSPERLYEAR; 01359 idelta = tdelta; 01360 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 01361 return NULL; 01362 if (idelta == 0) 01363 idelta = (tdays < 0) ? -1 : 1; 01364 newy = y; 01365 if (increment_overflow(&newy, idelta)) 01366 return NULL; 01367 leapdays = leaps_thru_end_of(newy - 1) - 01368 leaps_thru_end_of(y - 1); 01369 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 01370 tdays -= leapdays; 01371 y = newy; 01372 } 01373 01374 seconds = tdays * SECSPERDAY + 0.5; 01375 tdays = seconds / SECSPERDAY; 01376 rem += seconds - tdays * SECSPERDAY; 01377 01378 /* 01379 ** Given the range, we can now fearlessly cast... 01380 */ 01381 idays = tdays; 01382 rem += offset - corr; 01383 while (rem < 0) { 01384 rem += SECSPERDAY; 01385 --idays; 01386 } 01387 while (rem >= SECSPERDAY) { 01388 rem -= SECSPERDAY; 01389 ++idays; 01390 } 01391 while (idays < 0) { 01392 if (increment_overflow(&y, -1)) 01393 return NULL; 01394 idays += year_lengths[isleap(y)]; 01395 } 01396 while (idays >= year_lengths[isleap(y)]) { 01397 idays -= year_lengths[isleap(y)]; 01398 if (increment_overflow(&y, 1)) 01399 return NULL; 01400 } 01401 tmp->tm_year = y; 01402 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 01403 return NULL; 01404 tmp->tm_yday = idays; 01405 /* 01406 ** The "extra" mods below avoid overflow problems. 01407 */ 01408 tmp->tm_wday = EPOCH_WDAY + 01409 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 01410 (DAYSPERNYEAR % DAYSPERWEEK) + 01411 leaps_thru_end_of(y - 1) - 01412 leaps_thru_end_of(EPOCH_YEAR - 1) + 01413 idays; 01414 tmp->tm_wday %= DAYSPERWEEK; 01415 if (tmp->tm_wday < 0) 01416 tmp->tm_wday += DAYSPERWEEK; 01417 tmp->tm_hour = (int) (rem / SECSPERHOUR); 01418 rem %= SECSPERHOUR; 01419 tmp->tm_min = (int) (rem / SECSPERMIN); 01420 /* 01421 ** A positive leap second requires a special 01422 ** representation. This uses "... ??:59:60" et seq. 01423 */ 01424 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 01425 ip = mon_lengths[isleap(y)]; 01426 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 01427 idays -= ip[tmp->tm_mon]; 01428 tmp->tm_mday = (int) (idays + 1); 01429 tmp->tm_isdst = 0; 01430 #ifdef TM_GMTOFF 01431 tmp->TM_GMTOFF = offset; 01432 #endif /* defined TM_GMTOFF */ 01433 tmp->tm_usec = timep->tv_usec; 01434 return tmp; 01435 }
Definition at line 1490 of file localtime.c.
References ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, and ast_tm::tm_year.
01491 { 01492 int result; 01493 01494 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 01495 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 01496 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 01497 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 01498 (result = (atmp->tm_min - btmp->tm_min)) == 0 && 01499 (result = (atmp->tm_sec - btmp->tm_sec)) == 0) 01500 result = atmp->tm_usec - btmp->tm_usec; 01501 return result; 01502 }
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 682 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().
00683 { 00684 int leapyear; 00685 time_t value; 00686 int i; 00687 int d, m1, yy0, yy1, yy2, dow; 00688 00689 INITIALIZE(value); 00690 leapyear = isleap(year); 00691 switch (rulep->r_type) { 00692 00693 case JULIAN_DAY: 00694 /* 00695 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 00696 ** years. 00697 ** In non-leap years, or if the day number is 59 or less, just 00698 ** add SECSPERDAY times the day number-1 to the time of 00699 ** January 1, midnight, to get the day. 00700 */ 00701 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 00702 if (leapyear && rulep->r_day >= 60) 00703 value += SECSPERDAY; 00704 break; 00705 00706 case DAY_OF_YEAR: 00707 /* 00708 ** n - day of year. 00709 ** Just add SECSPERDAY times the day number to the time of 00710 ** January 1, midnight, to get the day. 00711 */ 00712 value = janfirst + rulep->r_day * SECSPERDAY; 00713 break; 00714 00715 case MONTH_NTH_DAY_OF_WEEK: 00716 /* 00717 ** Mm.n.d - nth "dth day" of month m. 00718 */ 00719 value = janfirst; 00720 for (i = 0; i < rulep->r_mon - 1; ++i) 00721 value += mon_lengths[leapyear][i] * SECSPERDAY; 00722 00723 /* 00724 ** Use Zeller's Congruence to get day-of-week of first day of 00725 ** month. 00726 */ 00727 m1 = (rulep->r_mon + 9) % 12 + 1; 00728 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 00729 yy1 = yy0 / 100; 00730 yy2 = yy0 % 100; 00731 dow = ((26 * m1 - 2) / 10 + 00732 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 00733 if (dow < 0) 00734 dow += DAYSPERWEEK; 00735 00736 /* 00737 ** "dow" is the day-of-week of the first day of the month. Get 00738 ** the day-of-month (zero-origin) of the first "dow" day of the 00739 ** month. 00740 */ 00741 d = rulep->r_day - dow; 00742 if (d < 0) 00743 d += DAYSPERWEEK; 00744 for (i = 1; i < rulep->r_week; ++i) { 00745 if (d + DAYSPERWEEK >= 00746 mon_lengths[leapyear][rulep->r_mon - 1]) 00747 break; 00748 d += DAYSPERWEEK; 00749 } 00750 00751 /* 00752 ** "d" is the day-of-month (zero-origin) of the day we want. 00753 */ 00754 value += d * SECSPERDAY; 00755 break; 00756 } 00757 00758 /* 00759 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 00760 ** question. To get the Epoch-relative time of the specified local 00761 ** time on that day, add the transition time and the current offset 00762 ** from UTC. 00763 */ 00764 return value + rulep->r_time + offset; 00765 }
static int tzload | ( | const char * | name, | |
struct state *const | sp, | |||
const int | doextend | |||
) | [static] |
Definition at line 260 of file localtime.c.
References state::ats, buf, 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, and TZDIR.
Referenced by ast_tzset(), gmtload(), and tzparse().
00261 { 00262 const char * p; 00263 int i; 00264 int fid; 00265 int stored; 00266 int nread; 00267 union { 00268 struct tzhead tzhead; 00269 char buf[2 * sizeof(struct tzhead) + 00270 2 * sizeof *sp + 00271 4 * TZ_MAX_TIMES]; 00272 } u; 00273 00274 if (name == NULL && (name = TZDEFAULT) == NULL) 00275 return -1; 00276 { 00277 int doaccess; 00278 /* 00279 ** Section 4.9.1 of the C standard says that 00280 ** "FILENAME_MAX expands to an integral constant expression 00281 ** that is the size needed for an array of char large enough 00282 ** to hold the longest file name string that the implementation 00283 ** guarantees can be opened." 00284 */ 00285 char fullname[FILENAME_MAX + 1]; 00286 00287 if (name[0] == ':') 00288 ++name; 00289 doaccess = name[0] == '/'; 00290 if (!doaccess) { 00291 if ((p = TZDIR) == NULL) 00292 return -1; 00293 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 00294 return -1; 00295 (void) strcpy(fullname, p); 00296 (void) strcat(fullname, "/"); 00297 (void) strcat(fullname, name); 00298 /* 00299 ** Set doaccess if '.' (as in "../") shows up in name. 00300 */ 00301 if (strchr(name, '.') != NULL) 00302 doaccess = TRUE; 00303 name = fullname; 00304 } 00305 if (doaccess && access(name, R_OK) != 0) 00306 return -1; 00307 if ((fid = open(name, OPEN_MODE)) == -1) 00308 return -1; 00309 } 00310 nread = read(fid, u.buf, sizeof u.buf); 00311 if (close(fid) < 0 || nread <= 0) 00312 return -1; 00313 for (stored = 4; stored <= 8; stored *= 2) { 00314 int ttisstdcnt; 00315 int ttisgmtcnt; 00316 00317 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 00318 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 00319 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 00320 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 00321 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 00322 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 00323 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 00324 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 00325 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 00326 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 00327 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 00328 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 00329 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 00330 return -1; 00331 if (nread - (p - u.buf) < 00332 sp->timecnt * stored + /* ats */ 00333 sp->timecnt + /* types */ 00334 sp->typecnt * 6 + /* ttinfos */ 00335 sp->charcnt + /* chars */ 00336 sp->leapcnt * (stored + 4) + /* lsinfos */ 00337 ttisstdcnt + /* ttisstds */ 00338 ttisgmtcnt) /* ttisgmts */ 00339 return -1; 00340 for (i = 0; i < sp->timecnt; ++i) { 00341 sp->ats[i] = (stored == 4) ? 00342 detzcode(p) : detzcode64(p); 00343 p += stored; 00344 } 00345 for (i = 0; i < sp->timecnt; ++i) { 00346 sp->types[i] = (unsigned char) *p++; 00347 if (sp->types[i] >= sp->typecnt) 00348 return -1; 00349 } 00350 for (i = 0; i < sp->typecnt; ++i) { 00351 struct ttinfo * ttisp; 00352 00353 ttisp = &sp->ttis[i]; 00354 ttisp->tt_gmtoff = detzcode(p); 00355 p += 4; 00356 ttisp->tt_isdst = (unsigned char) *p++; 00357 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 00358 return -1; 00359 ttisp->tt_abbrind = (unsigned char) *p++; 00360 if (ttisp->tt_abbrind < 0 || 00361 ttisp->tt_abbrind > sp->charcnt) 00362 return -1; 00363 } 00364 for (i = 0; i < sp->charcnt; ++i) 00365 sp->chars[i] = *p++; 00366 sp->chars[i] = '\0'; /* ensure '\0' at end */ 00367 for (i = 0; i < sp->leapcnt; ++i) { 00368 struct lsinfo * lsisp; 00369 00370 lsisp = &sp->lsis[i]; 00371 lsisp->ls_trans = (stored == 4) ? 00372 detzcode(p) : detzcode64(p); 00373 p += stored; 00374 lsisp->ls_corr = detzcode(p); 00375 p += 4; 00376 } 00377 for (i = 0; i < sp->typecnt; ++i) { 00378 struct ttinfo * ttisp; 00379 00380 ttisp = &sp->ttis[i]; 00381 if (ttisstdcnt == 0) 00382 ttisp->tt_ttisstd = FALSE; 00383 else { 00384 ttisp->tt_ttisstd = *p++; 00385 if (ttisp->tt_ttisstd != TRUE && 00386 ttisp->tt_ttisstd != FALSE) 00387 return -1; 00388 } 00389 } 00390 for (i = 0; i < sp->typecnt; ++i) { 00391 struct ttinfo * ttisp; 00392 00393 ttisp = &sp->ttis[i]; 00394 if (ttisgmtcnt == 0) 00395 ttisp->tt_ttisgmt = FALSE; 00396 else { 00397 ttisp->tt_ttisgmt = *p++; 00398 if (ttisp->tt_ttisgmt != TRUE && 00399 ttisp->tt_ttisgmt != FALSE) 00400 return -1; 00401 } 00402 } 00403 /* 00404 ** Out-of-sort ats should mean we're running on a 00405 ** signed time_t system but using a data file with 00406 ** unsigned values (or vice versa). 00407 */ 00408 for (i = 0; i < sp->timecnt - 2; ++i) 00409 if (sp->ats[i] > sp->ats[i + 1]) { 00410 ++i; 00411 if (TYPE_SIGNED(time_t)) { 00412 /* 00413 ** Ignore the end (easy). 00414 */ 00415 sp->timecnt = i; 00416 } else { 00417 /* 00418 ** Ignore the beginning (harder). 00419 */ 00420 int j; 00421 00422 for (j = 0; j + i < sp->timecnt; ++j) { 00423 sp->ats[j] = sp->ats[j + i]; 00424 sp->types[j] = sp->types[j + i]; 00425 } 00426 sp->timecnt = j; 00427 } 00428 break; 00429 } 00430 /* 00431 ** If this is an old file, we're done. 00432 */ 00433 if (u.tzhead.tzh_version[0] == '\0') 00434 break; 00435 nread -= p - u.buf; 00436 for (i = 0; i < nread; ++i) 00437 u.buf[i] = p[i]; 00438 /* 00439 ** If this is a narrow integer time_t system, we're done. 00440 */ 00441 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 00442 break; 00443 } 00444 if (doextend && nread > 2 && 00445 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 00446 sp->typecnt + 2 <= TZ_MAX_TYPES) { 00447 struct state ts; 00448 int result; 00449 00450 u.buf[nread - 1] = '\0'; 00451 result = tzparse(&u.buf[1], &ts, FALSE); 00452 if (result == 0 && ts.typecnt == 2 && 00453 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 00454 for (i = 0; i < 2; ++i) 00455 ts.ttis[i].tt_abbrind += 00456 sp->charcnt; 00457 for (i = 0; i < ts.charcnt; ++i) 00458 sp->chars[sp->charcnt++] = 00459 ts.chars[i]; 00460 i = 0; 00461 while (i < ts.timecnt && 00462 ts.ats[i] <= 00463 sp->ats[sp->timecnt - 1]) 00464 ++i; 00465 while (i < ts.timecnt && 00466 sp->timecnt < TZ_MAX_TIMES) { 00467 sp->ats[sp->timecnt] = 00468 ts.ats[i]; 00469 sp->types[sp->timecnt] = 00470 sp->typecnt + 00471 ts.types[i]; 00472 ++sp->timecnt; 00473 ++i; 00474 } 00475 sp->ttis[sp->typecnt++] = ts.ttis[0]; 00476 sp->ttis[sp->typecnt++] = ts.ttis[1]; 00477 } 00478 } 00479 i = 2 * YEARSPERREPEAT; 00480 sp->goback = sp->goahead = sp->timecnt > i; 00481 sp->goback = sp->goback && sp->types[i] == sp->types[0] && 00482 differ_by_repeat(sp->ats[i], sp->ats[0]); 00483 sp->goahead = sp->goahead && 00484 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && 00485 differ_by_repeat(sp->ats[sp->timecnt - 1], 00486 sp->ats[sp->timecnt - 1 - i]); 00487 return 0; 00488 }
static int tzparse | ( | const char * | name, | |
struct state * | sp, | |||
const int | lastditch | |||
) | [static] |
Definition at line 772 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, and tzload().
Referenced by ast_tzset(), and gmtload().
00773 { 00774 const char * stdname; 00775 const char * dstname; 00776 size_t stdlen; 00777 size_t dstlen; 00778 long stdoffset; 00779 long dstoffset; 00780 time_t * atp; 00781 unsigned char * typep; 00782 char * cp; 00783 int load_result; 00784 00785 INITIALIZE(dstname); 00786 stdname = name; 00787 if (lastditch) { 00788 stdlen = strlen(name); /* length of standard zone name */ 00789 name += stdlen; 00790 if (stdlen >= sizeof sp->chars) 00791 stdlen = (sizeof sp->chars) - 1; 00792 stdoffset = 0; 00793 } else { 00794 if (*name == '<') { 00795 name++; 00796 stdname = name; 00797 name = getqzname(name, '>'); 00798 if (*name != '>') 00799 return -1; 00800 stdlen = name - stdname; 00801 name++; 00802 } else { 00803 name = getzname(name); 00804 stdlen = name - stdname; 00805 } 00806 if (*name == '\0') 00807 return -1; 00808 name = getoffset(name, &stdoffset); 00809 if (name == NULL) 00810 return -1; 00811 } 00812 load_result = tzload(TZDEFRULES, sp, FALSE); 00813 if (load_result != 0) 00814 sp->leapcnt = 0; /* so, we're off a little */ 00815 if (*name != '\0') { 00816 if (*name == '<') { 00817 dstname = ++name; 00818 name = getqzname(name, '>'); 00819 if (*name != '>') 00820 return -1; 00821 dstlen = name - dstname; 00822 name++; 00823 } else { 00824 dstname = name; 00825 name = getzname(name); 00826 dstlen = name - dstname; /* length of DST zone name */ 00827 } 00828 if (*name != '\0' && *name != ',' && *name != ';') { 00829 name = getoffset(name, &dstoffset); 00830 if (name == NULL) 00831 return -1; 00832 } else dstoffset = stdoffset - SECSPERHOUR; 00833 if (*name == '\0' && load_result != 0) 00834 name = TZDEFRULESTRING; 00835 if (*name == ',' || *name == ';') { 00836 struct rule start; 00837 struct rule end; 00838 int year; 00839 time_t janfirst; 00840 time_t starttime; 00841 time_t endtime; 00842 00843 ++name; 00844 if ((name = getrule(name, &start)) == NULL) 00845 return -1; 00846 if (*name++ != ',') 00847 return -1; 00848 if ((name = getrule(name, &end)) == NULL) 00849 return -1; 00850 if (*name != '\0') 00851 return -1; 00852 sp->typecnt = 2; /* standard time and DST */ 00853 /* 00854 ** Two transitions per year, from EPOCH_YEAR forward. 00855 */ 00856 sp->ttis[0].tt_gmtoff = -dstoffset; 00857 sp->ttis[0].tt_isdst = 1; 00858 sp->ttis[0].tt_abbrind = stdlen + 1; 00859 sp->ttis[1].tt_gmtoff = -stdoffset; 00860 sp->ttis[1].tt_isdst = 0; 00861 sp->ttis[1].tt_abbrind = 0; 00862 atp = sp->ats; 00863 typep = sp->types; 00864 janfirst = 0; 00865 sp->timecnt = 0; 00866 for (year = EPOCH_YEAR; 00867 sp->timecnt + 2 <= TZ_MAX_TIMES; 00868 ++year) { 00869 time_t newfirst; 00870 00871 starttime = transtime(janfirst, year, &start, 00872 stdoffset); 00873 endtime = transtime(janfirst, year, &end, 00874 dstoffset); 00875 if (starttime > endtime) { 00876 *atp++ = endtime; 00877 *typep++ = 1; /* DST ends */ 00878 *atp++ = starttime; 00879 *typep++ = 0; /* DST begins */ 00880 } else { 00881 *atp++ = starttime; 00882 *typep++ = 0; /* DST begins */ 00883 *atp++ = endtime; 00884 *typep++ = 1; /* DST ends */ 00885 } 00886 sp->timecnt += 2; 00887 newfirst = janfirst; 00888 newfirst += year_lengths[isleap(year)] * 00889 SECSPERDAY; 00890 if (newfirst <= janfirst) 00891 break; 00892 janfirst = newfirst; 00893 } 00894 } else { 00895 long theirstdoffset; 00896 long theirdstoffset; 00897 long theiroffset; 00898 int isdst; 00899 int i; 00900 int j; 00901 00902 if (*name != '\0') 00903 return -1; 00904 /* 00905 ** Initial values of theirstdoffset and theirdstoffset. 00906 */ 00907 theirstdoffset = 0; 00908 for (i = 0; i < sp->timecnt; ++i) { 00909 j = sp->types[i]; 00910 if (!sp->ttis[j].tt_isdst) { 00911 theirstdoffset = 00912 -sp->ttis[j].tt_gmtoff; 00913 break; 00914 } 00915 } 00916 theirdstoffset = 0; 00917 for (i = 0; i < sp->timecnt; ++i) { 00918 j = sp->types[i]; 00919 if (sp->ttis[j].tt_isdst) { 00920 theirdstoffset = 00921 -sp->ttis[j].tt_gmtoff; 00922 break; 00923 } 00924 } 00925 /* 00926 ** Initially we're assumed to be in standard time. 00927 */ 00928 isdst = FALSE; 00929 theiroffset = theirstdoffset; 00930 /* 00931 ** Now juggle transition times and types 00932 ** tracking offsets as you do. 00933 */ 00934 for (i = 0; i < sp->timecnt; ++i) { 00935 j = sp->types[i]; 00936 sp->types[i] = sp->ttis[j].tt_isdst; 00937 if (sp->ttis[j].tt_ttisgmt) { 00938 /* No adjustment to transition time */ 00939 } else { 00940 /* 00941 ** If summer time is in effect, and the 00942 ** transition time was not specified as 00943 ** standard time, add the summer time 00944 ** offset to the transition time; 00945 ** otherwise, add the standard time 00946 ** offset to the transition time. 00947 */ 00948 /* 00949 ** Transitions from DST to DDST 00950 ** will effectively disappear since 00951 ** POSIX provides for only one DST 00952 ** offset. 00953 */ 00954 if (isdst && !sp->ttis[j].tt_ttisstd) { 00955 sp->ats[i] += dstoffset - 00956 theirdstoffset; 00957 } else { 00958 sp->ats[i] += stdoffset - 00959 theirstdoffset; 00960 } 00961 } 00962 theiroffset = -sp->ttis[j].tt_gmtoff; 00963 if (sp->ttis[j].tt_isdst) 00964 theirdstoffset = theiroffset; 00965 else theirstdoffset = theiroffset; 00966 } 00967 /* 00968 ** Finally, fill in ttis. 00969 ** ttisstd and ttisgmt need not be handled. 00970 */ 00971 sp->ttis[0].tt_gmtoff = -stdoffset; 00972 sp->ttis[0].tt_isdst = FALSE; 00973 sp->ttis[0].tt_abbrind = 0; 00974 sp->ttis[1].tt_gmtoff = -dstoffset; 00975 sp->ttis[1].tt_isdst = TRUE; 00976 sp->ttis[1].tt_abbrind = stdlen + 1; 00977 sp->typecnt = 2; 00978 } 00979 } else { 00980 dstlen = 0; 00981 sp->typecnt = 1; /* only standard time */ 00982 sp->timecnt = 0; 00983 sp->ttis[0].tt_gmtoff = -stdoffset; 00984 sp->ttis[0].tt_isdst = 0; 00985 sp->ttis[0].tt_abbrind = 0; 00986 } 00987 sp->charcnt = stdlen + 1; 00988 if (dstlen != 0) 00989 sp->charcnt += dstlen + 1; 00990 if ((size_t) sp->charcnt > sizeof sp->chars) 00991 return -1; 00992 cp = sp->chars; 00993 (void) strncpy(cp, stdname, stdlen); 00994 cp += stdlen; 00995 *cp++ = '\0'; 00996 if (dstlen != 0) { 00997 (void) strncpy(cp, dstname, dstlen); 00998 *(cp + dstlen) = '\0'; 00999 } 01000 return 0; 01001 }
char elsieid[] = "@(#)localtime.c 8.5" [static] |
Definition at line 67 of file localtime.c.
const char gmt[] = "GMT" [static] |
Definition at line 95 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 490 of file localtime.c.
Referenced by time2sub(), and timesub().
struct timeval WRONG = { 0, 0 } [static] |
Definition at line 96 of file localtime.c.
const int year_lengths[2] [static] |
Initial value:
{ DAYSPERNYEAR, DAYSPERLYEAR }
Definition at line 495 of file localtime.c.
Referenced by time2sub(), and timesub().