3 /// Timezone adjustment class, wrapping the TZ environment
4 /// variable to make struct tm -> time_t conversions easier.
8 Copyright (C) 2010, Chris Frey <cdfrey@foursquare.net>, To God be the glory
9 Released to the public domain.
12 #include "tzwrapper.h"
18 time_t utc_mktime(struct tm
*utctime
)
23 // loop, converting "local time" to time_t and back to utc tm,
24 // and adjusting until there are no differences... this
25 // automatically takes care of DST issues.
27 // do first conversion
30 result
= mktime(&tmp
);
31 if( result
== (time_t)-1 )
33 if( gmtime_r(&result
, &check
) == NULL
)
37 while( check
.tm_year
!= utctime
->tm_year
||
38 check
.tm_mon
!= utctime
->tm_mon
||
39 check
.tm_mday
!= utctime
->tm_mday
||
40 check
.tm_hour
!= utctime
->tm_hour
||
41 check
.tm_min
!= utctime
->tm_min
)
43 tmp
.tm_min
+= utctime
->tm_min
- check
.tm_min
;
44 tmp
.tm_hour
+= utctime
->tm_hour
- check
.tm_hour
;
45 tmp
.tm_mday
+= utctime
->tm_mday
- check
.tm_mday
;
46 tmp
.tm_year
+= utctime
->tm_year
- check
.tm_year
;
49 result
= mktime(&tmp
);
50 if( result
== (time_t)-1 )
52 gmtime_r(&result
, &check
);
53 if( gmtime_r(&result
, &check
) == NULL
)
60 struct tm
* iso_to_tm(const char *timestamp
,
64 memset(result
, 0, sizeof(struct tm
));
67 int found
= sscanf(timestamp
, "%04d%02d%02dT%02d%02d%02d%c",
68 &(result
->tm_year
), &(result
->tm_mon
), &(result
->tm_mday
),
69 &(result
->tm_hour
), &(result
->tm_min
), &(result
->tm_sec
),
72 result
->tm_year
-= 1900;
74 result
->tm_isdst
= -1;
76 utc
= (found
== 7 && zflag
== 'Z');
78 return (found
>= 6) ? result
: 0;
81 time_t TzWrapper::iso_mktime(const char *timestamp
)
85 if( !iso_to_tm(timestamp
, &t
, utc
) )
90 return tzw
.mktime(&t
);
99 using namespace reuse
;
102 time_t now
= time(NULL
);
104 cout
<< "TZ: " << TzWrapper().ctime(&now
);
105 cout
<< "UTC: " << TzWrapper("").ctime(&now
);
106 cout
<< "UTC: " << TzWrapper().SetUTC().ctime(&now
);
107 cout
<< "SysLocaltime: " << TzWrapper().SetUTC().SetSysLocal().ctime(&now
);
108 cout
<< "TZ: " << TzWrapper().SetUTC().SetDefault().ctime(&now
);
109 cout
<< "Canada/Eastern: " << TzWrapper("Canada/Eastern").ctime(&now
);
110 cout
<< "Canada/Pacific: " << TzWrapper("Canada/Pacific").ctime(&now
);
113 TzWrapper
tzw("UTC");
114 cout
<< "UTC: " << ctime(&now
);
117 cout
<< "TZ: " << ctime(&now
);
119 // test iso_mktime()... the test values assume a Canada/Eastern TZ
120 cout
<< "Using Canada/Eastern:" << endl
;
121 TzWrapper
tzw("Canada/Eastern");
122 const char *iso1
= "20100430T231500";
123 const char *iso2
= "20100501T031500Z";
124 time_t t1
= TzWrapper::iso_mktime(iso1
);
125 time_t t2
= TzWrapper::iso_mktime(iso2
);
126 cout
<< " " << iso1
<< ": (" << t1
<< ") " << ctime(&t1
);
127 cout
<< iso2
<< ": (" << t2
<< ") " << ctime(&t2
);
129 if( TzWrapper::iso_mktime("20100430") == (time_t)-1 )
130 cout
<< "Fail check: passed" << endl
;
132 cout
<< "Fail check: ERROR" << endl
;