Compute offset of local timezone from UTC for every day since 1880
This commit is contained in:
commit
c4f2035d21
|
@ -0,0 +1,2 @@
|
|||
CFLAGS = -std=c11 -Wall -ftrapv
|
||||
all: timezone-history
|
|
@ -0,0 +1,95 @@
|
|||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
time_t start_time(void) {
|
||||
// return the start of our time range
|
||||
// we want 12:00 local time on January 1st of the first year >= 1880
|
||||
// we can represent (1880, because time zones based on GMT were
|
||||
// enacted in 1885, so we start a little bit earlier if we can)
|
||||
for (int y = 1880; y < 2000; y++) {
|
||||
struct tm tm;
|
||||
tm.tm_year = y - 1900;
|
||||
tm.tm_mon = 0;
|
||||
tm.tm_mday = 1;
|
||||
tm.tm_hour = 12;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
time_t t = mktime(&tm);
|
||||
if (t != (time_t)-1) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
assert(0); // no date before 2000 representable? mktime is broken
|
||||
}
|
||||
|
||||
time_t end_time(void) {
|
||||
// return the end of our time range
|
||||
// 12:00 local time on dec. 31 of the current year seems ok.
|
||||
// we might want to extend that a few years into the future, but
|
||||
// it's hard to say how much: Sometimes DST changes are only
|
||||
// published weeks before they happen, so even the end of the year
|
||||
// is a bit optimistic.
|
||||
time_t t = time(NULL);
|
||||
struct tm *tmp = localtime(&t);
|
||||
|
||||
struct tm tm;
|
||||
tm.tm_year = tmp->tm_year;
|
||||
tm.tm_mon = 11;
|
||||
tm.tm_mday = 31;
|
||||
tm.tm_hour = 12;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
t = mktime(&tm);
|
||||
if (t != (time_t)-1) {
|
||||
return t;
|
||||
}
|
||||
assert(0); // end of current year not representable? mktime is broken
|
||||
}
|
||||
|
||||
int_least32_t diff(struct tm utm, struct tm ltm) {
|
||||
int_least32_t d;
|
||||
// local time should be close to noon, timezones are somwhere in
|
||||
// the +/- 14 hours range, so the UTC date can differ by at most one
|
||||
// date. Therefore we just check whether the UTC date is earlier or
|
||||
// later than the local date.
|
||||
if (ltm.tm_year > utm.tm_year) {
|
||||
d = 86400;
|
||||
} else if (ltm.tm_year < utm.tm_year) {
|
||||
d = -86400;
|
||||
} else {
|
||||
if (ltm.tm_mon > utm.tm_mon) {
|
||||
d = 86400;
|
||||
} else if (ltm.tm_mon < utm.tm_mon) {
|
||||
d = -86400;
|
||||
} else {
|
||||
if (ltm.tm_mday > utm.tm_mday) {
|
||||
d = 86400;
|
||||
} else if (ltm.tm_mday < utm.tm_mday) {
|
||||
d = -86400;
|
||||
} else {
|
||||
d = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
d += (ltm.tm_hour - utm.tm_hour) * 3600
|
||||
+ (ltm.tm_min - utm.tm_min) * 60
|
||||
+ (ltm.tm_sec - utm.tm_sec);
|
||||
return d;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
time_t start = start_time();
|
||||
time_t end = end_time();
|
||||
for (time_t t = start; t <= end; t += 24*3600) {
|
||||
struct tm utm = *(gmtime(&t));
|
||||
struct tm ltm = *(localtime(&t));
|
||||
int_least32_t d = diff(utm, ltm);
|
||||
printf("%.0f %.0f\n", (double)t, (double)d);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue