aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/util.c39
-rw-r--r--src/or/test.c15
2 files changed, 43 insertions, 11 deletions
diff --git a/src/common/util.c b/src/common/util.c
index 525f27b88..c81d0fe87 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -112,19 +112,36 @@ void tv_addms(struct timeval *a, long ms) {
a->tv_usec %= 1000000;
}
+
+#define IS_LEAPYEAR(y) (!(y % 4) && ((y % 100) || !(y % 400)))
+static int n_leapdays(int y1, int y2) {
+ --y1;
+ --y2;
+ return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
+}
+static const int days_per_month[] =
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
time_t tor_timegm (struct tm *tm) {
+ /* This is a pretty ironclad timegm implementation, snarfed from Python2.2.
+ * It's way more brute-force than fiddling with tzset().
+ */
time_t ret;
- char *tz;
-
- tz = getenv("TZ");
- setenv("TZ", "", 1);
- tzset();
- ret = mktime(tm);
- if (tz)
- setenv("TZ", tz, 1);
- else
- unsetenv("TZ");
- tzset();
+ unsigned long year, days, hours, minutes;
+ int i;
+ year = tm->tm_year + 1900;
+ assert(year >= 1970);
+ assert(tm->tm_mon >= 0 && tm->tm_mon <= 11);
+ days = 365 * (year-1970) + n_leapdays(1970,year);
+ for (i = 0; i < tm->tm_mon; ++i)
+ days += days_per_month[i];
+ if (tm->tm_mon > 1 && IS_LEAPYEAR(year))
+ ++days;
+ days += tm->tm_mday - 1;
+ hours = days*24 + tm->tm_hour;
+
+ minutes = hours*60 + tm->tm_min;
+ ret = minutes*60 + tm->tm_sec;
return ret;
}
diff --git a/src/or/test.c b/src/or/test.c
index 1d3c551b1..bdc6f43fb 100644
--- a/src/or/test.c
+++ b/src/or/test.c
@@ -422,6 +422,7 @@ test_crypto()
void
test_util() {
struct timeval start, end;
+ struct tm a_time;
start.tv_sec = 5;
start.tv_usec = 5000;
@@ -447,6 +448,20 @@ test_util() {
test_eq(0L, tv_udiff(&start, &end));
+ /* The test values here are confirmed to be correct on a platform
+ * with a working timgm. */
+ a_time.tm_year = 2003-1900;
+ a_time.tm_mon = 7;
+ a_time.tm_mday = 30;
+ a_time.tm_hour = 6;
+ a_time.tm_min = 14;
+ a_time.tm_sec = 55;
+ test_eq((time_t) 1062224095UL, tor_timegm(&a_time));
+ a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
+ test_eq((time_t) 1093846495UL, tor_timegm(&a_time));
+ a_time.tm_mon = 1; /* Try a leap year, in feb. */
+ a_time.tm_mday = 10;
+ test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
}
void