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