Index: funcs/func_strings.c =================================================================== --- funcs/func_strings.c (revision 112066) +++ funcs/func_strings.c (working copy) @@ -498,8 +498,15 @@ if (!strptime(args.timestring, args.format, &time)) { ast_log(LOG_WARNING, "C function strptime() output nothing?!!\n"); - } else { - snprintf(buf, len, "%d", (int) ast_mktime(&time, args.timezone)); + } else { /* strptime(3) does not support DST, so check it ourselves. */ + time_t found_time, unused_start, unused_end; + int gmt_off; + found_time = ast_mktime(&time, args.timezone); + ast_get_dst_info(&found_time, &time.tm_isdst, &unused_start, &unused_end, &gmt_off, args.timezone); + if (time.tm_isdst) { + found_time = ast_mktime(&time, args.timezone); + } + snprintf(buf, len, "%d", (int) found_time); } return 0; Index: include/asterisk/localtime.h =================================================================== --- include/asterisk/localtime.h (revision 112066) +++ include/asterisk/localtime.h (working copy) @@ -26,5 +26,6 @@ struct tm *ast_localtime(const time_t *timep, struct tm *p_tm, const char *zone); time_t ast_mktime(struct tm * const tmp, const char *zone); +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); #endif /* _ASTERISK_LOCALTIME_H */ Index: main/stdtime/localtime.c =================================================================== --- main/stdtime/localtime.c (revision 112066) +++ main/stdtime/localtime.c (working copy) @@ -1150,6 +1150,121 @@ } /* +** This function provides informaton about daylight savings time +** for the given timezone. This includes whether it can determine +** if daylight savings is used for this timezone, the UTC times for +** when daylight savings transitions, and the offset in seconds from +** UTC. +*/ + +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) +{ + 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; +} + +/* ** gmtsub is to gmtime as localsub is to localtime. */