lib: included tzwrapper in Barry and Barrified the namespace
[barry.git] / src / tzwrapper.cc
blobb5acef078d0cf3520ad8c4fb831adadec444fabb
1 ///
2 /// \file tzwrapper.cc
3 /// Timezone adjustment class, wrapping the TZ environment
4 /// variable to make struct tm -> time_t conversions easier.
5 ///
7 /*
8 Copyright (C) 2010, Chris Frey <cdfrey@foursquare.net>, To God be the glory
9 Released to the public domain.
10 Included in Barry and Barrified the namespace July 2010
13 #include "tzwrapper.h"
14 #include <string.h>
15 #include <stdio.h>
17 namespace Barry { namespace Sync {
19 time_t utc_mktime(struct tm *utctime)
21 time_t result;
22 struct tm tmp, check;
24 // loop, converting "local time" to time_t and back to utc tm,
25 // and adjusting until there are no differences... this
26 // automatically takes care of DST issues.
28 // do first conversion
29 tmp = *utctime;
30 tmp.tm_isdst = -1;
31 result = mktime(&tmp);
32 if( result == (time_t)-1 )
33 return (time_t)-1;
34 if( gmtime_r(&result, &check) == NULL )
35 return (time_t)-1;
37 // loop until match
38 while( check.tm_year != utctime->tm_year ||
39 check.tm_mon != utctime->tm_mon ||
40 check.tm_mday != utctime->tm_mday ||
41 check.tm_hour != utctime->tm_hour ||
42 check.tm_min != utctime->tm_min )
44 tmp.tm_min += utctime->tm_min - check.tm_min;
45 tmp.tm_hour += utctime->tm_hour - check.tm_hour;
46 tmp.tm_mday += utctime->tm_mday - check.tm_mday;
47 tmp.tm_year += utctime->tm_year - check.tm_year;
48 tmp.tm_isdst = -1;
50 result = mktime(&tmp);
51 if( result == (time_t)-1 )
52 return (time_t)-1;
53 gmtime_r(&result, &check);
54 if( gmtime_r(&result, &check) == NULL )
55 return (time_t)-1;
58 return result;
61 struct tm* iso_to_tm(const char *timestamp,
62 struct tm *result,
63 bool &utc)
65 memset(result, 0, sizeof(struct tm));
66 char zflag = 0;
68 int found = sscanf(timestamp, "%04d%02d%02dT%02d%02d%02d%c",
69 &(result->tm_year), &(result->tm_mon), &(result->tm_mday),
70 &(result->tm_hour), &(result->tm_min), &(result->tm_sec),
71 &zflag);
73 result->tm_year -= 1900;
74 result->tm_mon -= 1;
75 result->tm_isdst = -1;
77 utc = (found == 7 && zflag == 'Z');
79 return (found >= 6) ? result : 0;
82 time_t TzWrapper::iso_mktime(const char *timestamp)
84 bool utc;
85 struct tm t;
86 if( !iso_to_tm(timestamp, &t, utc) )
87 return (time_t)-1;
88 TzWrapper tzw;
89 if( utc )
90 tzw.SetUTC();
91 return tzw.mktime(&t);
94 }} // namespace Barry::Sync
97 #ifdef TZ_TEST_MODE
98 #include <iostream>
99 using namespace std;
100 using namespace Barry::Sync;
101 int main()
103 time_t now = time(NULL);
105 cout << "TZ: " << TzWrapper().ctime(&now);
106 cout << "UTC: " << TzWrapper("").ctime(&now);
107 cout << "UTC: " << TzWrapper().SetUTC().ctime(&now);
108 cout << "SysLocaltime: " << TzWrapper().SetUTC().SetSysLocal().ctime(&now);
109 cout << "TZ: " << TzWrapper().SetUTC().SetDefault().ctime(&now);
110 cout << "Canada/Eastern: " << TzWrapper("Canada/Eastern").ctime(&now);
111 cout << "Canada/Pacific: " << TzWrapper("Canada/Pacific").ctime(&now);
114 TzWrapper tzw("UTC");
115 cout << "UTC: " << ctime(&now);
118 cout << "TZ: " << ctime(&now);
120 // test iso_mktime()... the test values assume a Canada/Eastern TZ
121 cout << "Using Canada/Eastern:" << endl;
122 TzWrapper tzw("Canada/Eastern");
123 const char *iso1 = "20100430T231500";
124 const char *iso2 = "20100501T031500Z";
125 time_t t1 = TzWrapper::iso_mktime(iso1);
126 time_t t2 = TzWrapper::iso_mktime(iso2);
127 cout << " " << iso1 << ": (" << t1 << ") " << ctime(&t1);
128 cout << iso2 << ": (" << t2 << ") " << ctime(&t2);
130 if( TzWrapper::iso_mktime("20100430") == (time_t)-1 )
131 cout << "Fail check: passed" << endl;
132 else
133 cout << "Fail check: ERROR" << endl;
135 #endif