Custom localtime functions for multiple timezones. More...
#include <locale.h>

Go to the source code of this file.
Data Structures | |
| struct | ast_tm |
Typedefs | |
| typedef void * | locale_t |
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). | |
| void | ast_localtime_wakeup_monitor (struct ast_test *info) |
| struct timeval | ast_mktime (struct ast_tm *const tmp, const char *zone) |
| Timezone-independent version of mktime(3). | |
| const char * | ast_setlocale (const char *locale) |
| Set the thread-local representation of the current locale. | |
| 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. | |
| int | ast_strftime_locale (char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale) |
| 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. | |
| char * | ast_strptime_locale (const char *s, const char *format, struct ast_tm *tm, const char *locale) |
Custom localtime functions for multiple timezones.
Definition in file localtime.h.
| typedef void* locale_t |
Definition at line 32 of 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 1604 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().
{
int i;
int transition1 = -1;
int transition2 = -1;
time_t seconds;
int bounds_exceeded = 0;
time_t t = *timep;
const struct state *sp;
if (NULL == dst_enabled)
return;
*dst_enabled = 0;
if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
return;
*gmt_off = 0;
sp = ast_tzset(zone);
if (NULL == sp)
return;
/* If the desired time exceeds the bounds of the defined time transitions
* then give give up on determining DST info and simply look for gmt offset
* This requires that I adjust the given time using increments of Gregorian
* repeats to place the time within the defined time transitions in the
* timezone structure.
*/
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
time_t tcycles;
int_fast64_t icycles;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
++tcycles;
icycles = tcycles;
if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
return;
seconds = icycles;
seconds *= YEARSPERREPEAT;
seconds *= AVGSECSPERYEAR;
if (t < sp->ats[0])
t += seconds;
else
t -= seconds;
if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
return; /* "cannot happen" */
bounds_exceeded = 1;
}
if (sp->timecnt == 0 || t < sp->ats[0]) {
/* I have no transition times or I'm before time */
*dst_enabled = 0;
/* Find where I can get gmtoff */
i = 0;
while (sp->ttis[i].tt_isdst)
if (++i >= sp->typecnt) {
i = 0;
break;
}
*gmt_off = sp->ttis[i].tt_gmtoff;
return;
}
for (i = 1; i < sp->timecnt; ++i) {
if (t < sp->ats[i]) {
transition1 = sp->types[i - 1];
transition2 = sp->types[i];
break;
}
}
/* if I found transition times that do not bounded the given time and these correspond to
or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
(sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
*dst_enabled = 0;
*gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
} else {
/* I have valid daylight savings information. */
if(sp->ttis[transition2].tt_isdst)
*gmt_off = sp->ttis[transition1].tt_gmtoff;
else
*gmt_off = sp->ttis[transition2].tt_gmtoff;
/* If I adjusted the time earlier, indicate that the dst is invalid */
if (!bounds_exceeded) {
*dst_enabled = 1;
/* Determine which of the bounds is the start of daylight savings and which is the end */
if(sp->ttis[transition2].tt_isdst) {
*dst_start = sp->ats[i];
*dst_end = sp->ats[i -1];
} else {
*dst_start = sp->ats[i -1];
*dst_end = sp->ats[i];
}
}
}
return;
}
| 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 1589 of file localtime.c.
References ast_tzset(), and localsub().
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_check_timing2(), ast_http_send(), ast_log_full(), ast_queue_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_vi(), 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(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), make_logchannel(), manager_log(), mstime(), odbc_log(), packdate(), pgsql_log(), phone_call(), play_message_datetime(), prep_email_sub_vars(), 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_definetimedate(), transmit_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().
| void ast_localtime_wakeup_monitor | ( | struct ast_test * | info | ) |
Definition at line 626 of file localtime.c.
References ast_cond_wait, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, and lock.
{
if (inotify_thread != AST_PTHREADT_NULL) {
AST_LIST_LOCK(&zonelist);
#ifdef TEST_FRAMEWORK
test = info;
#endif
pthread_kill(inotify_thread, SIGURG);
ast_cond_wait(&initialization, &(&zonelist)->lock);
#ifdef TEST_FRAMEWORK
test = NULL;
#endif
AST_LIST_UNLOCK(&zonelist);
}
}
| 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 2204 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), icalfloat_to_timet(), mstime_to_time_t(), rt_extend_conf(), sms_handleincoming_proto2(), sms_readfile(), testtime_write(), and unpackdate().
| const char* ast_setlocale | ( | const char * | locale | ) |
Set the thread-local representation of the current locale.
Definition at line 2267 of file localtime.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_name(), locale_entry::locale, locale_entry::name, and store_by_locale().
Referenced by ast_strftime_locale(), and ast_strptime_locale().
{
struct locale_entry *cur;
locale_t prevlocale = LC_GLOBAL_LOCALE;
if (locale == NULL) {
return store_by_locale(uselocale(LC_GLOBAL_LOCALE));
}
AST_LIST_LOCK(&localelist);
if ((cur = find_by_name(locale))) {
prevlocale = uselocale(cur->locale);
}
if (!cur) {
if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) {
cur->locale = newlocale(LC_ALL_MASK, locale, NULL);
strcpy(cur->name, locale); /* SAFE */
AST_LIST_INSERT_TAIL(&localelist, cur, list);
prevlocale = uselocale(cur->locale);
}
}
AST_LIST_UNLOCK(&localelist);
return store_by_locale(prevlocale);
}
| 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. |
| locale | Text string specifying the locale to be used for language strings. |
| An | integer value specifying the number of bytes placed into buf or -1 on error. |
Definition at line 2370 of file localtime.c.
References ast_strftime_locale().
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_http_send(), ast_log_full(), ast_queue_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), conf_run(), dump_datetime(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), isodate(), leave_voicemail(), make_email_file(), make_logchannel(), manager_log(), mstime(), odbc_log(), pgsql_log(), rt_extend_conf(), sendmail(), sendpage(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().
{
return ast_strftime_locale(buf, len, tmp, tm, NULL);
}
| int ast_strftime_locale | ( | char * | buf, |
| size_t | len, | ||
| const char * | format, | ||
| const struct ast_tm * | tm, | ||
| const char * | locale | ||
| ) |
Definition at line 2299 of file localtime.c.
References ast_calloc, ast_free, ast_realloc, ast_setlocale(), format, and ast_tm::tm_usec.
Referenced by ast_strftime(), make_email_file(), prep_email_sub_vars(), and sendpage().
{
size_t fmtlen = strlen(tmp) + 1;
char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
int decimals = -1, i, res;
long fraction;
const char *prevlocale;
if (!format) {
return -1;
}
for (; *tmp; tmp++) {
if (*tmp == '%') {
switch (tmp[1]) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
if (tmp[2] != 'q') {
goto defcase;
}
decimals = tmp[1] - '0';
tmp++;
/* Fall through */
case 'q': /* Milliseconds */
if (decimals == -1) {
decimals = 3;
}
/* Juggle some memory to fit the item */
newfmt = ast_realloc(format, fmtlen + decimals);
if (!newfmt) {
ast_free(format);
return -1;
}
fptr = fptr - format + newfmt;
format = newfmt;
fmtlen += decimals;
/* Reduce the fraction of time to the accuracy needed */
for (i = 6, fraction = tm->tm_usec; i > decimals; i--) {
fraction /= 10;
}
fptr += sprintf(fptr, "%0*ld", decimals, fraction);
/* Reset, in case more than one 'q' specifier exists */
decimals = -1;
tmp++;
break;
default:
goto defcase;
}
} else {
defcase: *fptr++ = *tmp;
}
}
*fptr = '\0';
#undef strftime
if (locale) {
prevlocale = ast_setlocale(locale);
}
res = (int)strftime(buf, len, format, (struct tm *)tm);
if (locale) {
ast_setlocale(prevlocale);
}
ast_free(format);
return res;
}
| 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. |
| locale | Text string specifying the locale to be used for language strings. |
| A | pointer to the first character within s not used to parse the date and time. |
Definition at line 2396 of file localtime.c.
References ast_strptime_locale().
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), mstime_to_time_t(), rt_extend_conf(), and testtime_write().
{
return ast_strptime_locale(s, format, tm, NULL);
}
| char* ast_strptime_locale | ( | const char * | s, |
| const char * | format, | ||
| struct ast_tm * | tm, | ||
| const char * | locale | ||
| ) |
Definition at line 2375 of file localtime.c.
References ast_setlocale(), ast_tm::tm_isdst, and ast_tm::tm_usec.
Referenced by ast_strptime().
{
struct tm tm2 = { 0, };
char *res;
const char *prevlocale;
prevlocale = ast_setlocale(locale);
res = strptime(s, format, &tm2);
ast_setlocale(prevlocale);
/* ast_time and tm are not the same size - tm is a subset of
* ast_time. Hence, the size of tm needs to be used for the
* memcpy
*/
memcpy(tm, &tm2, sizeof(tm2));
tm->tm_usec = 0;
/* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
* to deal with it correctly, we set it to -1. */
tm->tm_isdst = -1;
return res;
}