Custom localtime functions for multiple timezones. More...

Go to the source code of this file.
Data Structures | |
| struct | ast_tm |
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) |
| struct ast_tm * | ast_localtime (const struct timeval *timep, struct ast_tm *p_tm, const char *zone) |
| Timezone-independent version of localtime_r(3). | |
| struct timeval | ast_mktime (struct ast_tm *const tmp, const char *zone) |
| Timezone-independent version of mktime(3). | |
| int | ast_strftime (char *buf, size_t len, const char *format, const struct ast_tm *tm) |
| Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds. | |
| char * | ast_strptime (const char *s, const char *format, struct ast_tm *tm) |
| Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use. | |
Custom localtime functions for multiple timezones.
Definition in file localtime.h.
| 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 1320 of file localtime.c.
References ast_tzset(), state::ats, state::goahead, state::goback, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and state::types.
Referenced by set_timezone_variables().
01321 { 01322 int i; 01323 int transition1 = -1; 01324 int transition2 = -1; 01325 time_t seconds; 01326 int bounds_exceeded = 0; 01327 time_t t = *timep; 01328 const struct state *sp; 01329 01330 if (NULL == dst_enabled) 01331 return; 01332 *dst_enabled = 0; 01333 01334 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off) 01335 return; 01336 01337 *gmt_off = 0; 01338 01339 sp = ast_tzset(zone); 01340 if (NULL == sp) 01341 return; 01342 01343 /* If the desired time exceeds the bounds of the defined time transitions 01344 * then give give up on determining DST info and simply look for gmt offset 01345 * This requires that I adjust the given time using increments of Gregorian 01346 * repeats to place the time within the defined time transitions in the 01347 * timezone structure. 01348 */ 01349 if ((sp->goback && t < sp->ats[0]) || 01350 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 01351 time_t tcycles; 01352 int_fast64_t icycles; 01353 01354 if (t < sp->ats[0]) 01355 seconds = sp->ats[0] - t; 01356 else seconds = t - sp->ats[sp->timecnt - 1]; 01357 --seconds; 01358 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01359 ++tcycles; 01360 icycles = tcycles; 01361 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01362 return; 01363 seconds = icycles; 01364 seconds *= YEARSPERREPEAT; 01365 seconds *= AVGSECSPERYEAR; 01366 if (t < sp->ats[0]) 01367 t += seconds; 01368 else 01369 t -= seconds; 01370 01371 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1]) 01372 return; /* "cannot happen" */ 01373 01374 bounds_exceeded = 1; 01375 } 01376 01377 if (sp->timecnt == 0 || t < sp->ats[0]) { 01378 /* I have no transition times or I'm before time */ 01379 *dst_enabled = 0; 01380 /* Find where I can get gmtoff */ 01381 i = 0; 01382 while (sp->ttis[i].tt_isdst) 01383 if (++i >= sp->typecnt) { 01384 i = 0; 01385 break; 01386 } 01387 *gmt_off = sp->ttis[i].tt_gmtoff; 01388 return; 01389 } 01390 01391 for (i = 1; i < sp->timecnt; ++i) { 01392 if (t < sp->ats[i]) { 01393 transition1 = sp->types[i - 1]; 01394 transition2 = sp->types[i]; 01395 break; 01396 } 01397 } 01398 /* if I found transition times that do not bounded the given time and these correspond to 01399 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */ 01400 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 || 01401 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) { 01402 *dst_enabled = 0; 01403 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff; 01404 } else { 01405 /* I have valid daylight savings information. */ 01406 if(sp->ttis[transition2].tt_isdst) 01407 *gmt_off = sp->ttis[transition1].tt_gmtoff; 01408 else 01409 *gmt_off = sp->ttis[transition2].tt_gmtoff; 01410 01411 /* If I adjusted the time earlier, indicate that the dst is invalid */ 01412 if (!bounds_exceeded) { 01413 *dst_enabled = 1; 01414 /* Determine which of the bounds is the start of daylight savings and which is the end */ 01415 if(sp->ttis[transition2].tt_isdst) { 01416 *dst_start = sp->ats[i]; 01417 *dst_end = sp->ats[i -1]; 01418 } else { 01419 *dst_start = sp->ats[i -1]; 01420 *dst_end = sp->ats[i]; 01421 } 01422 } 01423 } 01424 return; 01425 }
| struct ast_tm* ast_localtime | ( | const struct timeval * | timep, | |
| struct ast_tm * | p_tm, | |||
| const char * | zone | |||
| ) | [read] |
Timezone-independent version of localtime_r(3).
| timep | Current time, including microseconds | |
| p_tm | Pointer to memory where the broken-out time will be stored | |
| zone | Text string of a standard system zoneinfo file. If NULL, the system localtime will be used. |
| p_tm | is returned for convenience |
Definition at line 1305 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(), conf_run(), enc_ie_date(), execute_cb(), find_conf_realtime(), format_date(), 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(), odbc_log(), packdate(), pgsql_log(), phone_call(), phoneprov_callback(), play_message_datetime(), prep_email_sub_vars(), rpt_localtime(), rt_extend_conf(), say_date_generic(), send_date_time(), send_date_time2(), send_date_time3(), sendmail(), set_timezone_variables(), sip_show_registry(), sms_compose2(), sms_handleincoming_proto2(), static_callback(), timeout_write(), transmit_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().
| struct timeval ast_mktime | ( | struct ast_tm *const | tmp, | |
| const char * | zone | |||
| ) | [read] |
Timezone-independent version of mktime(3).
| tmp | Current broken-out time, including microseconds | |
| zone | Text string of a standard system zoneinfo file. If NULL, the system localtime will be used. |
| A | structure containing both seconds and fractional thereof since January 1st, 1970 UTC |
Definition at line 1920 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), rt_extend_conf(), sms_handleincoming_proto2(), sms_readfile(), and unpackdate().
| int ast_strftime | ( | char * | buf, | |
| size_t | len, | |||
| const char * | format, | |||
| const struct ast_tm * | tm | |||
| ) |
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds.
| buf | Address in memory where the resulting string will be stored. | |
| len | Size of the chunk of memory buf. | |
| format | A string specifying the format of time to be placed into buf. | |
| tm | Pointer to the broken out time to be used for the format. |
| An | integer value specifying the number of bytes placed into buf or -1 on error. |
Definition at line 1928 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(), conf_run(), dump_datetime(), execute_cb(), find_conf_realtime(), format_date(), get_date(), handle_minivm_show_stats(), handle_show_settings(), httpd_helper_thread(), isodate(), leave_voicemail(), make_email_file(), manager_log(), odbc_log(), pgsql_log(), phoneprov_callback(), prep_email_sub_vars(), rt_extend_conf(), sendmail(), sendpage(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().
01929 { 01930 size_t fmtlen = strlen(tmp) + 1; 01931 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt; 01932 int decimals = -1, i, res; 01933 long fraction; 01934 01935 if (!format) 01936 return -1; 01937 for (; *tmp; tmp++) { 01938 if (*tmp == '%') { 01939 switch (tmp[1]) { 01940 case '1': 01941 case '2': 01942 case '3': 01943 case '4': 01944 case '5': 01945 case '6': 01946 if (tmp[2] != 'q') 01947 goto defcase; 01948 decimals = tmp[1] - '0'; 01949 tmp++; 01950 /* Fall through */ 01951 case 'q': /* Milliseconds */ 01952 if (decimals == -1) 01953 decimals = 3; 01954 01955 /* Juggle some memory to fit the item */ 01956 newfmt = ast_realloc(format, fmtlen + decimals); 01957 if (!newfmt) { 01958 ast_free(format); 01959 return -1; 01960 } 01961 fptr = fptr - format + newfmt; 01962 format = newfmt; 01963 fmtlen += decimals; 01964 01965 /* Reduce the fraction of time to the accuracy needed */ 01966 for (i = 6, fraction = tm->tm_usec; i > decimals; i--) 01967 fraction /= 10; 01968 fptr += sprintf(fptr, "%0*ld", decimals, fraction); 01969 01970 /* Reset, in case more than one 'q' specifier exists */ 01971 decimals = -1; 01972 tmp++; 01973 break; 01974 default: 01975 goto defcase; 01976 } 01977 } else 01978 defcase: *fptr++ = *tmp; 01979 } 01980 *fptr = '\0'; 01981 #undef strftime 01982 res = (int)strftime(buf, len, format, (struct tm *)tm); 01983 ast_free(format); 01984 return res; 01985 }
| char* ast_strptime | ( | const char * | s, | |
| const char * | format, | |||
| struct ast_tm * | tm | |||
| ) |
Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.
| s | A string specifying some portion of a date and time. | |
| format | The format in which the string, s, is expected. | |
| tm | The broken-out time structure into which the parsed data is expected. |
| A | pointer to the first character within s not used to parse the date and time. |
Definition at line 1987 of file localtime.c.
References ast_tm::tm_isdst, and ast_tm::tm_usec.
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), and rt_extend_conf().
01988 { 01989 struct tm tm2 = { 0, }; 01990 char *res = strptime(s, format, &tm2); 01991 memcpy(tm, &tm2, sizeof(*tm)); 01992 tm->tm_usec = 0; 01993 /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3) 01994 * to deal with it correctly, we set it to -1. */ 01995 tm->tm_isdst = -1; 01996 return res; 01997 }
1.6.2