Thu Apr 28 2011 17:13:57

Asterisk developer's documentation


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, AVGSECSPERYEAR, 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:
timepCurrent time, including microseconds
p_tmPointer to memory where the broken-out time will be stored
zoneText string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
p_tmis 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:
tmpCurrent broken-out time, including microseconds
zoneText string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
Astructure 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:
bufAddress in memory where the resulting string will be stored.
lenSize of the chunk of memory buf.
formatA string specifying the format of time to be placed into buf.
tmPointer to the broken out time to be used for the format.
Return values:
Aninteger 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:
sA string specifying some portion of a date and time.
formatThe format in which the string, s, is expected.
tmThe broken-out time structure into which the parsed data is expected.
Return values:
Apointer 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;
}