Search code examples
c++c++11c++-chrono

Is it possible to get time_point from zoned_time?


I tried to get local time / UTC selectively in std::string.

  1. What I've tried:

(1) getting std::string for UTC works fine with std::format:

auto utc = std::chrono::system_clock::now(); 
std::string sTime = std::format("{:%H%M%S}", utc);

(2) and local time:

auto zoned = std::chrono::zoned_time{ "Asia/Seoul", std::chrono::system_clock::now() }; 
sTime = std::format("{:%H%M%S}", zoned);
  1. What I want to achieve:

But they have different types. How can I achieve a functionality like this?

bool b = true;
sTime = std::format("{:%H%M%S}", b? utc : zoned);

Solution

  • zoned_time has two getters:

    .get_sys_time()    // get the utc time
    .get_local_time()  // get the local time
    

    It can do this because zoned_time is just a convenience data structure that holds {time_zone const*, sys_time}. If you ask it for the sys_time, it just returns what it has. If you ask it for the local_time, it uses the time_zone to change the sys_time into local_time.

    And if you format a zoned_time then it formats local time.

    So:

    auto zoned = std::chrono::zoned_time{ "Asia/Seoul", std::chrono::system_clock::now() }; 
    std::string sTime;
    if (b)
        sTime = std::format("{:%H%M%S}", zoned.get_sys_time());
    else
        sTime = std::format("{:%H%M%S}", zoned);
    

    Or wrap that up in a function for a one-liner:

    auto choose_time = [](bool b, auto zoned)
    {
        if (b)
            return std::format("{:%H%M%S}", zoned.get_sys_time());
        return std::format("{:%H%M%S}", zoned);
    };
    
    bool b = true;
    auto zoned = std::chrono::zoned_time{ "Asia/Seoul", std::chrono::system_clock::now() }; 
    auto sTime = choose_time(b, zoned);
    

    Update

    @starriet주녕차 makes a good observation in a comment below that when you want local time in choose_time that zoned is "good enough" as opposed to zoned.get_local_time().

    And in this particular example, the two are equivalent. However I thought it worthwhile to point out when zoned is actually a superior choice:

    If the format specification asks for time zone abbreviation (%Z) or time zone offset (%z), then zoned (which has type zoned_time) has this information and can can supply it, and zoned.get_local_time() (which has type local_time) does not.

    Additionally zoned.get_sys_time() can also format %Z (as "UTC") or %z (as "0000"). The type of zoned.get_sys_time() is sys_time and has the semantics of Unix Time.

    Whereas local_time has the semantics of: It is a local time which has yet to be paired with a time_zone. And zoned_time is effectively that pairing.