Reputation: 191
I have this little example below that is giving me results that I don't understand.
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
int main() {
auto currentTime = std::time(nullptr);
auto currentTime2 = std::time(nullptr);
std::stringstream ss;
std::stringstream ss2;
ss << std::put_time(std::localtime(¤tTime), "%Y-%m-%dT%H:%M:%S %z %Z");
ss2 << std::put_time(std::gmtime(¤tTime2), "%Y-%m-%dT%H:%M:%S %z %Z");
std::cout << " time now local = " << ss.str() << std::endl;
std::cout << " time now gm = " << ss2.str() << std::endl;
}
On Windows (VS2017) this gives me:
time now local = 2019-10-08T16:25:17 +0200 W. Europe Summer Time
time now gm = 2019-10-08T14:25:17 +0100 W. Europe Standard Time
On Mac (XCode 10) this gives me:
time now local = 2019-10-08T16:25:17 +0200 CEST
time now gm = 2019-10-08T14:25:17 +0100 UTC
Could someone explain to me why the %z gives +0100 for the UTC outputs instead of +0000? What part of logic am I missing?
Running this on http://ideone.com/IspjpG for example always gives +0000.
Upvotes: 3
Views: 1894
Reputation: 238401
The std::tm
class returned by std::gmtime
and std::localtime
does not contain timezone information, other than whether daylight saving is in effect. For gmtime
, it is never in effect and for localtime
, it depends on current locale and time.
%Z
format specifier of std::put_time
uses the current locale for timezone information. The currently active locale is unaffected by the std::tm
object given as argument.
So in first case, you print the local time with information about local timezone (with DST enabled). And in second case, you print UTC time with information about local timezone (with DST disabled).
We can conclude that using %z
and %Z
is incorrect for printing times from other timezones than the current local one. Frankly, I consider it a flaw in std::put_time
interface (and the interface of std::strftime
, which std::put_time
wraps) that one cannot pass timezone information to the function, but can accidentally print a timezone that may be unrelated to the std::tm
instance being printed.
For correct output, you should use:
ss2 << std::put_time(std::gmtime(¤tTime2),
"%Y-%m-%dT%H:%M:%S +0000 UTC");
Upvotes: 4