3

I've problem with use of the std::localtime function. When I transform a std::time_t to a local struct tm, it always use the american daylight saving time whereas I want to use the european one (France).

UTC : 03/19/16 16:56 is transformed in Local : 03/19/16 18:56.

At this date, normally, local is 17:56 (UTC+1). The DST happens on the 27th in France. After several tests, it seems that the used DST is based on the american rule : DST happens on second sunday in march.

I've also changed the TZ environement variable, but it also fails.


`

if( putenv( "TZ=CET-1CEST-2,M3.5.0/2,M10.5.0/3" ) != 0 ) { 
     std::cout << "Unable to set TZ" << std::endl; 
} else { 
   tz = getenv("TZ"); 
   if (tz) std::cout << tz << std::endl; 
   else std::cout << "TZ not defined" << std::endl; tzset(); 
}

struct std::tm t;
t.tm_sec = 0;
t.tm_min = 56;
t.tm_hour = 18;
t.tm_mday = 19;
t.tm_mon = 3-1;
t.tm_year = 2016-1900;
t.tm_isdst = -1;
std::time_t tt = std::mktime(&t);
std::cout << "UTC: " << std::put_time(std::gmtime(&tt), "%c %Z") << '\n'; // UTC : 03/19/16 16:56
std::cout << "local: " << std::put_time(std::localtime(&tt), "%c %Z") << '\n'; // Local : 03/19/16 18:56 (not waited result)

`

As a precision, I use the bcc32c compiler (the embarcadero C++ clang based computer).

I hope I'm clear enough and you'll be able to help me.

Thanks in advance

1 Answers1

1

If you have C++11 (or later) available, which includes <chrono>, and if you are willing to work with the <chrono> system. And if you are willing to use this free, open-source timezone library. Then this is a very simple matter:

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono_literals;
    auto zt = make_zoned("Europe/Paris", sys_days{2016_y/mar/19} + 18h + 56min);
    std::cout << format("%m/%d/%y %H:%M %Z", zt.get_sys_time()) << '\n';
    std::cout << format("%m/%d/%y %H:%M %Z", zt) << '\n';
}

Output:

03/19/16 18:56 UTC
03/19/16 19:56 CET

In short, you form one zoned_time by pairing a timezone of your choosing ("Europe/Paris"), with a sys_time (UTC). Then you can format that zoned_time both by extracting the sys_time back out of it, and by formatting the zoned_time itself, which will use the local_time of the zoned_time.

I attempted to use formatting that was consistent with your comments. You could of course you any format you want. You can also include any std::locale your system supports as the first argument in the calls to format (which %c would take advantage of).

You can also extract individual fields both from the sys_time and from the local_time if you need to, or do other date or time computations. This is more than just a formatting library.

If you are starting with a time_t, there is a static member function of std::chrono::system_clock to convert a time_t to a system_clock::time_point. You can then use that time_point in place of sys_days{2016_y/mar/19} + 18h + 56min in this example:

auto zt = make_zoned("Europe/Paris", system_clock::from_time_t(t));
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • @MathiasVantieghem: If you have any troubles or questions, you can chat on gitter (linked off the README at github). Start a github issue. Ping me here. Or email me directly (just search for my email address, it is easy to find). – Howard Hinnant Jun 30 '16 at 14:11