Tue Aug 24 2010 19:41:54

Asterisk developer's documentation


Data Structures | Functions

localtime.h File Reference

Custom localtime functions for multiple timezones. More...

This graph shows which files directly or indirectly include this file:

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_tmast_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.

Detailed Description

Custom localtime functions for multiple timezones.

Definition in file localtime.h.


Function Documentation

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 1321 of file localtime.c.

References ast_tzset(), state::ats, state::goahead, state::goback, int_fast64_t, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

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).

Parameters:
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.
Return values:
p_tm is returned for convenience

Definition at line 1306 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().

{
   const struct state *sp = ast_tzset(zone);
   memset(tmp, 0, sizeof(*tmp));
   return sp ? localsub(timep, 0L, tmp, sp) : NULL;
}

struct timeval ast_mktime ( struct ast_tm *const   tmp,
const char *  zone 
) [read]

Timezone-independent version of mktime(3).

Parameters:
tmp Current broken-out time, including microseconds
zone Text string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
A structure containing both seconds and fractional thereof since January 1st, 1970 UTC

Definition at line 1921 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().

{
   const struct state *sp;
   if (!(sp = ast_tzset(zone)))
      return WRONG;
   return time1(tmp, localsub, 0L, sp);
}

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.

Parameters:
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.
Return values:
An integer value specifying the number of bytes placed into buf or -1 on error.

Definition at line 1929 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().

{
   size_t fmtlen = strlen(tmp) + 1;
   char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
   int decimals = -1, i, res;
   long fraction;

   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
   res = (int)strftime(buf, len, format, (struct tm *)tm);
   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.

Parameters:
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.
Return values:
A pointer to the first character within s not used to parse the date and time.

Definition at line 1988 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().

{
   struct tm tm2 = { 0, };
   char *res = strptime(s, format, &tm2);
   memcpy(tm, &tm2, sizeof(*tm));
   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;
}