aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/timezone_conversion/convert.cpp
blob: 490bb4e2700caccae8907d121eb192d2c1030c25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "convert.h"

#include <contrib/libs/cctz/include/cctz/civil_time.h>

#include <util/generic/yexception.h>

#include <chrono>

namespace NDatetime {
    static constexpr i64 TM_YEAR_OFFSET = 1900;
    using TSystemClock = std::chrono::system_clock;
    using TTimePoint = std::chrono::time_point<TSystemClock>;

    static TSimpleTM CivilToTM(const cctz::civil_second& cs, const cctz::time_zone::absolute_lookup& al) {
        cctz::civil_day cd(cs);
        TSimpleTM tm;
        tm.GMTOff = al.offset;
        tm.Year = cs.year() - TM_YEAR_OFFSET;
        tm.YDay = cctz::get_yearday(cd);
        tm.Mon = cs.month() - 1;
        tm.MDay = cs.day();
        tm.Hour = cs.hour();
        tm.Min = cs.minute();
        tm.Sec = cs.second();
        tm.IsDst = al.is_dst;
        tm.IsLeap = LeapYearAD(cs.year());

        switch (cctz::get_weekday(cd)) {
            case cctz::weekday::monday:
                tm.WDay = 1;
                break;
            case cctz::weekday::tuesday:
                tm.WDay = 2;
                break;
            case cctz::weekday::wednesday:
                tm.WDay = 3;
                break;
            case cctz::weekday::thursday:
                tm.WDay = 4;
                break;
            case cctz::weekday::friday:
                tm.WDay = 5;
                break;
            case cctz::weekday::saturday:
                tm.WDay = 6;
                break;
            case cctz::weekday::sunday:
                tm.WDay = 0;
                break;
        }

        return tm;
    }

    /*
    TTimeZone GetTimeZone(const TString& name) {
        TTimeZone result;
        if (!cctz::load_time_zone(name, &result)) {
            ythrow yexception() << "Failed to load time zone " << name << ", " << result.name();
        }
        return result;
    }
    */

    TTimeZone GetUtcTimeZone() {
        return cctz::utc_time_zone();
    }

    TTimeZone GetLocalTimeZone() {
        return cctz::local_time_zone();
    }

    TSimpleTM ToCivilTime(const TInstant& absoluteTime, const TTimeZone& tz) {
        TTimePoint tp = TSystemClock::from_time_t(absoluteTime.TimeT());
        return CivilToTM(cctz::convert(tp, tz), tz.lookup(tp));
    }

    TSimpleTM CreateCivilTime(const TTimeZone& tz, ui32 year, ui32 mon, ui32 day, ui32 h, ui32 m, ui32 s) {
        cctz::civil_second cs(year, mon, day, h, m, s);
        return CivilToTM(cs, tz.lookup(tz.lookup(cs).pre));
    }

    TInstant ToAbsoluteTime(const TSimpleTM& civilTime, const TTimeZone& tz) {
        cctz::civil_second cs(
            civilTime.Year + TM_YEAR_OFFSET,
            civilTime.Mon + 1,
            civilTime.MDay,
            civilTime.Hour,
            civilTime.Min,
            civilTime.Sec);
        return TInstant::Seconds(TSystemClock::to_time_t(tz.lookup(cs).pre));
    }
}