16 #define TIME_FMT_PRIVATE
31 #ifdef HAVE_SYS_TIME_H
53 log_warn(
LD_BUG,
"%s", err);
72 log_warn(
LD_BUG,
"%s", err);
79 #define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
86 return (year2/4 - year1/4) - (year2/100 - year1/100)
87 + (year2/400 - year1/400);
92 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
107 int64_t year, days, hours, minutes, seconds;
108 int i, invalid_year, dpm;
116 if (tm->tm_year < INT32_MAX-1900) {
117 year = tm->tm_year + 1900;
122 invalid_year = (year < 1970 || tm->tm_year >= INT32_MAX-1900);
124 if (tm->tm_mon >= 0 && tm->tm_mon <= 11) {
126 if (tm->tm_mon == 1 && !invalid_year &&
IS_LEAPYEAR(tm->tm_year)) {
135 tm->tm_mon < 0 || tm->tm_mon > 11 ||
136 tm->tm_mday < 1 || tm->tm_mday > dpm ||
137 tm->tm_hour < 0 || tm->tm_hour > 23 ||
138 tm->tm_min < 0 || tm->tm_min > 59 ||
139 tm->tm_sec < 0 || tm->tm_sec > 60) {
140 log_warn(
LD_BUG,
"Out-of-range argument to tor_timegm");
143 days = 365 * (year-1970) +
n_leapdays(1970,(
int)year);
144 for (i = 0; i < tm->tm_mon; ++i)
148 days += tm->tm_mday - 1;
149 hours = days*24 + tm->tm_hour;
151 minutes = hours*60 + tm->tm_min;
152 seconds = minutes*60 + tm->tm_sec;
157 #if SIZEOF_TIME_T < 8
158 if (seconds < TIME_MIN || seconds > TIME_MAX) {
159 log_warn(
LD_BUG,
"Result does not fit in tor_timegm");
163 *time_out = (time_t)seconds;
181 time_t result = timegm((
struct tm *) tm);
183 log_warn(
LD_BUG,
"timegm() could not convert time: %s", strerror(errno));
200 {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat" };
203 {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
204 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec" };
219 strftime(buf, RFC1123_TIME_LEN+1,
"___, %d ___ %Y %H:%M:%S GMT", &tm);
242 int i, m, invalid_year;
243 unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
246 if (strlen(buf) != RFC1123_TIME_LEN)
248 memset(&tm, 0,
sizeof(tm));
249 if (
tor_sscanf(buf,
"%3s, %2u %3s %u %2u:%2u:%2u GMT", weekday,
250 &tm_mday, month, &tm_year, &tm_hour,
251 &tm_min, &tm_sec) < 7) {
253 log_warn(
LD_GENERAL,
"Got invalid RFC1123 time %s", esc);
259 for (i = 0; i < 12; ++i) {
267 log_warn(
LD_GENERAL,
"Got invalid RFC1123 time %s: No such month", esc);
273 invalid_year = (tm_year >= INT32_MAX || tm_year < 1970);
276 if (m == 1 && !invalid_year &&
IS_LEAPYEAR(tm_year)) {
280 if (invalid_year || tm_mday < 1 || tm_mday > dpm ||
281 tm_hour > 23 || tm_min > 59 || tm_sec > 60) {
283 log_warn(
LD_GENERAL,
"Got invalid RFC1123 time %s", esc);
287 tm.tm_mday = (int)tm_mday;
288 tm.tm_year = (int)tm_year;
289 tm.tm_hour = (int)tm_hour;
290 tm.tm_min = (int)tm_min;
291 tm.tm_sec = (int)tm_sec;
293 if (tm.tm_year < 1970) {
300 "Got invalid RFC1123 time %s. (Before 1970)", esc);
319 strftime(buf, ISO_TIME_LEN+1,
"%Y-%m-%d %H:%M:%S",
tor_localtime_r(&t, &tm));
329 strftime(buf, ISO_TIME_LEN+1,
"%Y-%m-%d %H:%M:%S",
tor_gmtime_r(&t, &tm));
358 tor_snprintf(buf+ISO_TIME_LEN, 8,
".%06d", (
int)tv->tv_usec);
370 unsigned int year=0, month=0, day=0, hour=0, minute=0, second=0;
372 char extra_char, separator_char;
373 n_fields =
tor_sscanf(cp,
"%u-%2u-%2u%c%2u:%2u:%2u%c",
376 &hour, &minute, &second, &extra_char);
377 if (strict ? (n_fields != 7) : (n_fields < 7)) {
379 log_warn(
LD_GENERAL,
"ISO time %s was unparseable", esc);
383 if (separator_char != (nospace ?
'T' :
' ')) {
385 log_warn(
LD_GENERAL,
"ISO time %s was unparseable", esc);
389 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
390 hour > 23 || minute > 59 || second > 60 || year >= INT32_MAX) {
392 log_warn(
LD_GENERAL,
"ISO time %s was nonsensical", esc);
396 st_tm.tm_year = (int)year-1900;
397 st_tm.tm_mon = month-1;
399 st_tm.tm_hour = hour;
400 st_tm.tm_min = minute;
401 st_tm.tm_sec = second;
404 if (st_tm.tm_year < 70) {
410 log_warn(
LD_GENERAL,
"Got invalid ISO time %s. (Before 1970)", esc);
446 unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
449 memset(tm, 0,
sizeof(*tm));
452 if ((cp = strchr(date,
','))) {
457 if (
tor_sscanf(cp,
"%2u %3s %4u %2u:%2u:%2u GMT",
458 &tm_mday, month, &tm_year,
459 &tm_hour, &tm_min, &tm_sec) == 6) {
462 }
else if (
tor_sscanf(cp,
"%2u-%3s-%2u %2u:%2u:%2u GMT",
463 &tm_mday, month, &tm_year,
464 &tm_hour, &tm_min, &tm_sec) == 6) {
471 if (
tor_sscanf(date,
"%3s %3s %2u %2u:%2u:%2u %4u",
472 wkday, month, &tm_mday,
473 &tm_hour, &tm_min, &tm_sec, &tm_year) == 7) {
479 tm->tm_mday = (int)tm_mday;
480 tm->tm_year = (int)tm_year;
481 tm->tm_hour = (int)tm_hour;
482 tm->tm_min = (int)tm_min;
483 tm->tm_sec = (int)tm_sec;
490 for (i = 0; i < 12; ++i) {
496 if (tm->tm_year < 0 ||
497 tm->tm_mon < 0 || tm->tm_mon > 11 ||
498 tm->tm_mday < 1 || tm->tm_mday > 31 ||
499 tm->tm_hour < 0 || tm->tm_hour > 23 ||
500 tm->tm_min < 0 || tm->tm_min > 59 ||
501 tm->tm_sec < 0 || tm->tm_sec > 60)
515 long sec = 0, min = 0, hour = 0, day = 0;
518 if (interval < -LONG_MAX)
520 else if (interval < 0)
521 interval = -interval;
523 if (interval >= 86400) {
524 day = interval / 86400;
527 if (interval >= 3600) {
528 hour = interval / 3600;
531 if (interval >= 60) {
538 return tor_snprintf(out, out_len,
"%ld days, %ld hours, %ld minutes",
541 return tor_snprintf(out, out_len,
"%ld hours, %ld minutes", hour, min);
543 return tor_snprintf(out, out_len,
"%ld minutes, %ld seconds", min, sec);
char * esc_for_log(const char *s)
Headers for util_malloc.c.
int tor_snprintf(char *str, size_t size, const char *format,...)
int tor_sscanf(const char *buf, const char *pattern,...)
Definitions for timing-related constants.
static const char * MONTH_NAMES[]
void format_iso_time_nospace(char *buf, time_t t)
void format_rfc1123_time(char *buf, time_t t)
int parse_iso_time(const char *cp, time_t *t)
int parse_http_time(const char *date, struct tm *tm)
void format_iso_time_nospace_usec(char *buf, const struct timeval *tv)
void format_iso_time(char *buf, time_t t)
int parse_iso_time_(const char *cp, time_t *t, int strict, int nospace)
static const char * WEEKDAY_NAMES[]
void format_local_iso_time_nospace(char *buf, time_t t)
int parse_rfc1123_time(const char *buf, time_t *t)
ATTR_UNUSED STATIC int tor_timegm_impl(const struct tm *tm, time_t *time_out)
void format_local_iso_time(char *buf, time_t t)
static const int days_per_month[]
int tor_timegm(const struct tm *tm, time_t *time_out)
struct tm * tor_gmtime_r(const time_t *timep, struct tm *result)
static int n_leapdays(int year1, int year2)
int format_time_interval(char *out, size_t out_len, long interval)
int parse_iso_time_nospace(const char *cp, time_t *t)
struct tm * tor_localtime_r(const time_t *timep, struct tm *result)
struct tm * tor_localtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
struct tm * tor_gmtime_r_msg(const time_t *timep, struct tm *result, char **err_out)
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()