/** * This outputs a list of timezone changes for the given timezone to the * given file, up to the maximum year given. We compare this output with the * output from 'vzic --dump-changes' to make sure that we are consistent. * (vzic is the Olson timezone database to VTIMEZONE converter.) * * The output format is: * * Zone-Name [tab] Date [tab] Time [tab] UTC-Offset * * The Date and Time fields specify the time change in UTC. * * The UTC Offset is for local (wall-clock) time. It is the amount of time * to add to UTC to get local time. */ int icaltimezone_dump_changes (icaltimezone *zone, int max_year, FILE *fp) { static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; icaltimezonechange *zone_change; int change_num; char buffer[8]; /* Make sure the changes array is expanded up to the given time. */ icaltimezone_ensure_coverage (zone, max_year); #if 0 printf ("Num changes: %i\n", zone->changes->num_elements); #endif change_num = 0; for (change_num = 0; change_num < zone->changes->num_elements; change_num++) { zone_change = icalarray_element_at (zone->changes, change_num); if (zone_change->year > max_year) break; fprintf (fp, "%s\t%2i %s %04i\t%2i:%02i:%02i", zone->location, zone_change->day, months[zone_change->month - 1], zone_change->year, zone_change->hour, zone_change->minute, zone_change->second); /* Wall Clock Time offset from UTC. */ format_utc_offset (zone_change->utc_offset, buffer); fprintf (fp, "\t%s", buffer); fprintf (fp, "\n"); } return 1; }
static bool istrftime(char *buf, size_t size, char const *time_fmt, struct tm const *tm, time_t t, char const *ab, char const *zone_name) { char *b = buf; size_t s = size; char const *f = time_fmt, *p; for (p = f; ; p++) if (*p == '%' && p[1] == '%') p++; else if (!*p || (*p == '%' && (p[1] == 'f' || p[1] == 'L' || p[1] == 'Q'))) { size_t formatted_len; size_t f_prefix_len = p - f; size_t f_prefix_copy_size = p - f + 2; char fbuf[100]; bool oversized = sizeof fbuf <= f_prefix_copy_size; char *f_prefix_copy = oversized ? xmalloc(f_prefix_copy_size) : fbuf; memcpy(f_prefix_copy, f, f_prefix_len); strcpy(f_prefix_copy + f_prefix_len, "X"); formatted_len = strftime(b, s, f_prefix_copy, tm); if (oversized) free(f_prefix_copy); if (formatted_len == 0) return false; formatted_len--; b += formatted_len, s -= formatted_len; if (!*p++) break; switch (*p) { case 'f': formatted_len = format_quoted_string(b, s, zone_name); break; case 'L': formatted_len = format_local_time(b, s, tm); break; case 'Q': { bool show_abbr; int offlen = format_utc_offset(b, s, tm, t); if (! (0 <= offlen && (size_t)offlen < s)) return false; show_abbr = strcmp(b, ab) != 0; b += offlen, s -= offlen; if (show_abbr) { char const *abp; size_t len; if (s <= 1) return false; *b++ = '\t', s--; for (abp = ab; is_alpha(*abp); abp++) continue; len = (!*abp && *ab ? (size_t)snprintf(b, s, "%s", ab) : format_quoted_string(b, s, ab)); if (s <= len) return false; b += len, s -= len; } formatted_len = (tm->tm_isdst ? snprintf(b, s, &"\t\t%d"[show_abbr], tm->tm_isdst) : 0); } break; } if (! (formatted_len < s)) return false; b += formatted_len, s -= formatted_len; f = p + 1; } *b = '\0'; return true; }