Struct offset_datetime

Synopsis

#include <toml/datetime.hpp>

struct offset_datetime

Description

No description yet.

Methods

offset_datetime overload
~offset_datetime
operator std::chrono::system_clock::time_point
operator std::time_t
operator= overload

Source

Lines 479-593 in toml/datetime.hpp.

struct offset_datetime
{
    local_date  date;
    local_time  time;
    time_offset offset;

    offset_datetime(local_date d, local_time t, time_offset o)
        : date(d), time(t), offset(o)
    {}
    offset_datetime(const local_datetime& dt, time_offset o)
        : date(dt.date), time(dt.time), offset(o)
    {}
    explicit offset_datetime(const local_datetime& ld)
        : date(ld.date), time(ld.time), offset(get_local_offset(nullptr))
          // use the current local timezone offset
    {}
    explicit offset_datetime(const std::chrono::system_clock::time_point& tp)
        : offset(0, 0) // use gmtime
    {
        const auto timet = std::chrono::system_clock::to_time_t(tp);
        const auto tm    = detail::gmtime_s(&timet);
        this->date = local_date(tm);
        this->time = local_time(tm);
    }
    explicit offset_datetime(const std::time_t& t)
        : offset(0, 0) // use gmtime
    {
        const auto tm    = detail::gmtime_s(&t);
        this->date = local_date(tm);
        this->time = local_time(tm);
    }
    explicit offset_datetime(const std::tm& t)
        : offset(0, 0) // assume gmtime
    {
        this->date = local_date(t);
        this->time = local_time(t);
    }

    operator std::chrono::system_clock::time_point() const
    {
        // get date-time
        using internal_duration =
            typename std::chrono::system_clock::time_point::duration;

        // first, convert it to local date-time information in the same way as
        // local_datetime does. later we will use time_t to adjust time offset.
        std::tm t;
        t.tm_sec   = static_cast<int>(this->time.second);
        t.tm_min   = static_cast<int>(this->time.minute);
        t.tm_hour  = static_cast<int>(this->time.hour);
        t.tm_mday  = static_cast<int>(this->date.day);
        t.tm_mon   = static_cast<int>(this->date.month);
        t.tm_year  = static_cast<int>(this->date.year) - 1900;
        t.tm_wday  = 0; // the value will be ignored
        t.tm_yday  = 0; // the value will be ignored
        t.tm_isdst = -1;
        const std::time_t tp_loc = std::mktime(std::addressof(t));

        auto tp = std::chrono::system_clock::from_time_t(tp_loc);
        tp += std::chrono::duration_cast<internal_duration>(
                std::chrono::milliseconds(this->time.millisecond) +
                std::chrono::microseconds(this->time.microsecond) +
                std::chrono::nanoseconds (this->time.nanosecond));

        // Since mktime uses local time zone, it should be corrected.
        // `12:00:00+09:00` means `03:00:00Z`. So mktime returns `03:00:00Z` if
        // we are in `+09:00` timezone. To represent `12:00:00Z` there, we need
        // to add `+09:00` to `03:00:00Z`.
        //    Here, it uses the time_t converted from date-time info to handle
        // daylight saving time.
        const auto ofs = get_local_offset(std::addressof(tp_loc));
        tp += std::chrono::hours  (ofs.hour);
        tp += std::chrono::minutes(ofs.minute);

        // We got `12:00:00Z` by correcting local timezone applied by mktime.
        // Then we will apply the offset. Let's say `12:00:00-08:00` is given.
        // And now, we have `12:00:00Z`. `12:00:00-08:00` means `20:00:00Z`.
        // So we need to subtract the offset.
        tp -= std::chrono::minutes(this->offset);
        return tp;
    }

    operator std::time_t() const
    {
        return std::chrono::system_clock::to_time_t(
                std::chrono::system_clock::time_point(*this));
    }

    offset_datetime() = default;
    ~offset_datetime() = default;
    offset_datetime(offset_datetime const&) = default;
    offset_datetime(offset_datetime&&)      = default;
    offset_datetime& operator=(offset_datetime const&) = default;
    offset_datetime& operator=(offset_datetime&&)      = default;

  private:

    static time_offset get_local_offset(const std::time_t* tp)
    {
        // get local timezone with the same date-time information as mktime
        const auto t = detail::localtime_s(tp);

        std::array<char, 6> buf;
        const auto result = std::strftime(buf.data(), 6, "%z", &t); // +hhmm\0
        if(result != 5)
        {
            throw std::runtime_error("toml::offset_datetime: cannot obtain "
                                     "timezone information of current env");
        }
        const int ofs = std::atoi(buf.data());
        const int ofs_h = ofs / 100;
        const int ofs_m = ofs - (ofs_h * 100);
        return time_offset(ofs_h, ofs_m);
    }
};





Add Discussion as Guest

Log in