Reputation: 2320
The following code shall print the time with the time zone offset, the lowercase format specifier z
is passed:
#include <iostream>
#include <iomanip>
#include <ctime>
using namespace std;
int main() {
time_t current_time = time(nullptr);
tm* timeinfo = localtime(¤t_time);
cout << put_time(timeinfo, "%c %z") << "\n";
return 0;
}
g++ -o time time.cpp -Wall -pedantic
The function put_time() (C++) is described on cppreference.com. The format specifiers are the ones from strftime() (C). You can also read about them in the C Standard, currently page 396 in chapter 7.27.3.5:
%z
is replaced by the offset from UTC in the ISO 8601 format ‘‘−0430’’ (meaning 4 hours 30 minutes behind UTC, west of Greenwich), or by no characters if no time zone is determinable. [tm_isdst]
This works well on Linux:
Fri Jul 26 12:30:02 2019 +0200
But on Windows it's returning:
07/26/19 12:03:53 Mitteleuropäisches Sommerzeit
That's wrong, my code doesn't ask for the name of the timezone, but for the offset to UTC. I'm using on both platforms GCC as compiler.
Question
Am I doing something wrong here? Or is either GCC or Microsoft Windows violating the standard? I read some "rumors" about that it could be influenced through some settings on Windows.
Caluclating the offset by hand is rather treacherous. The best helper would be tm.gmt_offset, which is platform specific field. Therefore gmt_offset
is not listed and only available on GNU based systems. I'm currently using a workaround based on GetTimeZoneInformation and the fields Bias
and DaylightBias
, which is a platform specific Windows-API. I appreciate more secure suggestions.
Thank you for help and insights!
Environments:
GNU/Linux with GCC 9.1.0 (Archlinux)
Windows with GCC 8.3.0 (MSYS2)
Upvotes: 1
Views: 420
Reputation: 219205
If you are willing to use a free, open-source (MIT license) 3rd party library, it will give portable results.
#include "date/tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
zoned_seconds zt{current_zone(), floor<seconds>(system_clock::now())};
cout << format("%c %z", zt) << '\n';
}
Though on Windows you will need to install curl and 7-zip, and on linux you'll need to link with -lcurl
. More detailed installation instructions are available here.
This is a preview of the draft C++20 <chrono>
library, though admittedly the syntax for the format
statement is going to change slightly due to votes being taken just last week in Cologne. C++20 will incorporate the fmt library (which is great news).
This library still uses put_time
for the %c
part of the format, but formats the %z
part itself (and gives the offset in [+/-]hhmm
form as desired).
Upvotes: 1