Search code examples
c++boosttimeboost-date-time

Time conversion between timezones


I have a server application that works in GMT. My application communicates with a server in the Berlin timezone, I read some files from time to time from this server. And I need to compare the times from this files. How can I convert the remote server time from the Berlin timezone to GMT considering summer, winter time shifts? Do you know mb something from boost.date_time can help me to do it easily?

I am not trying to convert from local time to gmt. I am converting from a specific timezone to gmt. I need to have a robust way of doing it with different timezones.


Solution

  • Perhaps this free, open source, C++11/14 timezone library could be of help. You can use it to convert UTC to or from your local timezone, to or from any arbitrary IANA timezone, or between any two arbitrary IANA timezones. The library has been ported to gcc, clang, and VS. But it requires <chrono>.

    Here is a short example of how you can get the current UTC time, convert that to Berlin local time, then convert the Berlin local time to your local time, then convert the Berlin local time back to UTC. It is all quite easy, using modern C++ syntax and type safety:

    #include "tz.h"
    #include <iostream>
    
    int
    main()
    {
        using namespace date;
        using namespace std::chrono;
        auto utc = system_clock::now();
        auto berlin = make_zoned("Europe/Berlin", utc);
        auto local  = make_zoned(current_zone(), berlin);
        auto utc2   = berlin.get_sys_time();
        std::cout << format("%F %T %Z", utc) << '\n';
        std::cout << format("%F %T %Z", berlin) << '\n';
        std::cout << format("%F %T %Z", local) << '\n';
        std::cout << format("%F %T %Z", utc2) << '\n';
    }
    

    This just output for me:

    2016-07-05 01:41:29.207335 UTC
    2016-07-05 03:41:29.207335 CEST
    2016-07-04 21:41:29.207335 EDT
    2016-07-05 01:41:29.207335 UTC
    

    Yes, you can even transition timezones with whatever precision your std::chrono::sytem_clock supports, and parse and format that precision.

    If this library gives you any trouble, you can get help here on stack overflow, or chat here, or open an issue here, or search for my email address and contact me directly.

    This library is fully documented, and designed to stay up-to-date with the very latest IANA timezone database (even if you need the latest mess the Egyptian politicians have made -- making a timezone rule change with a whole 3 days advance notice). And if your timestamps are antiquated (say from the 1940s), do not worry. This library seamlessly supports the full timezone history that IANA provides. That is, if there is data in the IANA timezone database, this library extracts and uses it without error.

    You can also easily and efficiently form date literals local to Berlin if that is helpful to your application. For example, here is how you would specify 15:30 on the first Monday of July 2016 in Berlin (<chrono> literals require C++14):

    auto meet = make_zoned("Europe/Berlin", local_days{2016_y/jul/mon[1]} + 15h + 30min);
    std::cout << meet << '\n';
    

    Output:

    2016-07-04 15:30:00 CEST
    

    If you want to find out what time the New York office has to telecommute in for this meeting:

    std::cout <<  make_zoned("America/New_York", meet) << '\n';
    

    Output:

    2016-07-04 09:30:00 EDT
    

    Hope this helps.

    C++20 Update

    You can now do this in C++20, without the free, open source library, with very similar syntax (on those platforms where it has been implemented):

    #include <chrono>
    #include <format>
    #include <iostream>
    
    int
    main()
    {
        using namespace std::chrono;
    
        auto utc = system_clock::now();
        auto berlin = zoned_time{"Europe/Berlin", utc};
        auto local  = zoned_time{current_zone(), berlin};
        auto utc2   = berlin.get_sys_time();
        std::cout << std::format("{:%F %T %Z}", utc) << '\n';
        std::cout << std::format("{:%F %T %Z}", berlin) << '\n';
        std::cout << std::format("{:%F %T %Z}", local) << '\n';
        std::cout << std::format("{:%F %T %Z}", utc2) << '\n';
        auto meet = zoned_time{"Europe/Berlin", local_days{2016y/July/Monday[1]} + 15h + 30min};
        std::cout << meet << '\n';
        std::cout <<  zoned_time{"America/New_York", meet} << '\n';
    }
    

    Demo.