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.
10 Included in Barry and Barrified the namespace July 2010
13 #ifndef __TZWRAPPER_H__
20 namespace Barry
{ namespace Sync
{
22 /// Parses ISO timestamp in the format of YYYYMMDDTHHMMSS[Z]
23 /// or YYYY-MM-DDTHH:MM:SS.uuu-HH:MM
24 /// and places broken down time in result.
25 /// The trailing Z is optional in the format.
26 /// If the Z exists, utc will be set to true, otherwise false.
27 /// If zoneminutes is not null, and if a timezone offset is
28 /// specified, it will be filled in and *zone set to true.
29 /// Otherwise, *zone will be set to false.
30 /// Returns NULL on error.
32 BXEXPORT
struct tm
* iso_to_tm(const char *timestamp
,
36 int *zoneminutes
= 0);
38 /// Turns the struct tm into an ISO timestamp in the format
39 /// of YYYYMMDDTHHMMSS[Z]. The Z is appended if utc is true.
40 /// This function assumes that t contains sane values, and will
41 /// create the target string directly from its content.
42 /// Returns the ISO timestamp, or empty string on error.
43 /// If t contains sane values, this function should never fail.
45 BXEXPORT
std::string
tm_to_iso(const struct tm
*t
, bool utc
);
47 /// utc_mktime() converts a struct tm that contains
48 /// broken down time in utc to a time_t. This function uses
49 /// a brute-force method of conversion that does not require
50 /// the environment variable TZ to be changed at all, and is
51 /// therefore slightly more thread-safe in that regard.
53 /// The difference between mktime() and utc_mktime() is that
54 /// standard mktime() expects the struct tm to be in localtime,
55 /// according to the current TZ and system setting, while utc_mktime()
56 /// always assumes that the struct tm is in UTC, and converts it
57 /// to time_t regardless of what TZ is currently set.
59 /// The difference between utc_mktime() and TzWrapper::iso_mktime()
60 /// is that iso_mktime() will parse straight from an ISO string,
61 /// and if the ISO timestamp ends in a 'Z', it will behave like
62 /// utc_mktime() except it will alter the TZ environment variable
63 /// to do it. If the ISO timestamp has no 'Z', then iso_mktime()
64 /// behaves like mktime().
66 BXEXPORT
time_t utc_mktime(struct tm
*utctime
);
71 /// Wrapper class for the TZ environment variable. This class allows
72 /// setting TZ to any number of variables, and will restore the original
73 /// setting on destruction.
75 /// By default, TzWrapper does not change the environment at all, but
76 /// only saves it. Alternately, you can use the timezone constructor
77 /// to save and set a new timezone on the fly.
79 /// Each Set() and Unset() function returns a reference to TzWrapper,
80 /// so that you can chain function calls like this:
82 /// time_t utc = TzWrapper("Canada/Pacific").mktime(&pacific_tm);
84 /// In addition, there are two static utility functions used to
85 /// convert ISO timestamps to struct tm* and time_t values.
87 /// Note: This class is not thread-safe, since it modifies the TZ
88 /// environment variable without locking. If other threads
89 /// use time functions, this may interfere with their behaviour.
91 class BXEXPORT TzWrapper
93 std::string m_orig_tz
;
100 char *ptz
= getenv("TZ");
110 Set(m_orig_tz
.c_str());
119 /// Does not change TZ, only saves current setting
126 /// Saves current setting and sets TZ to new timezone value.
127 /// If timezone is null, it is the same as calling Unset().
128 explicit TzWrapper(const char *timezone
)
140 /// Set TZ to a new value. If timezone is null, it is the
141 /// same as calling Unset().
143 /// If timezone is an empty or invalid timezone string, it
144 /// is the same as calling SetUTC().
145 TzWrapper
& Set(const char *timezone
)
148 setenv("TZ", timezone
, 1);
156 /// Deletes TZ from the environment, which has the same effect
157 /// as calling SetSysLocal(). This is not a permanent
158 /// condition, since TZ will be restored to original state
159 /// upon destruction.
168 /// Set timezone to UTC
174 /// Set timezone via offset in minutes
175 /// Negative minutes goes west, positive goes east
176 /// i.e. -05:00 is EST
177 TzWrapper
& SetOffset(int zoneminutes
);
179 /// Use system localtime. This overrides any TZ value that the
180 /// user may have set before running your program.
181 TzWrapper
& SetSysLocal()
186 /// Use the default TZ value that the user set before running
187 /// this program. In most cases, this will be the user's
188 /// preferred local timezone.
189 TzWrapper
& SetDefault()
194 /// Same as SetDefault()
201 // C library wrappers, for calls like:
202 // time_t t = TzWrapper("Canada/Pacific").mktime(tm);
204 char* asctime(const struct tm
*t
) const { return ::asctime(t
); }
205 char* asctime_r(const struct tm
*t
, char *buf
) const
206 { return ::asctime_r(t
, buf
); }
207 char* ctime(const time_t *t
) const { return ::ctime(t
); }
208 char* ctime_r(const time_t *t
, char *buf
) const
209 { return ::ctime_r(t
, buf
); }
210 struct tm
* gmtime(const time_t *t
) const { return ::gmtime(t
); }
211 struct tm
* gmtime_r(const time_t *t
, struct tm
*result
) const
212 { return ::gmtime_r(t
, result
); }
213 struct tm
* localtime(const time_t *t
) const { return ::localtime(t
); }
214 struct tm
* localtime_r(const time_t *t
, struct tm
*result
) const
215 { return ::localtime_r(t
, result
); }
216 time_t mktime(struct tm
*t
) { return ::mktime(t
); }
219 // Additional utility functions
222 /// Converts an ISO timestamp (YYYYMMDDTHHMMWW[Z]) into a
223 /// unix time_t. If the 'Z' UTC flag is not specified, then
224 /// the timestamp will be assumed to be in the current
225 /// default timezone. Otherwise, SetUTC() will be used for the
228 /// This function uses an internal TzWrapper to adjust TZ
229 /// if necessary, which is why it is a static function
230 /// of TzWrapper, instead of a standalone function.
232 static time_t iso_mktime(const char *timestamp
);
235 }} // namespace Barry::Sync