1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // Copyright (C) 2016 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QDATETIME_P_H |
6 | #define QDATETIME_P_H |
7 | |
8 | // |
9 | // W A R N I N G |
10 | // ------------- |
11 | // |
12 | // This file is not part of the Qt API. It exists purely as an |
13 | // implementation detail. This header file may change from version to |
14 | // version without notice, or even be removed. |
15 | // |
16 | // We mean it. |
17 | // |
18 | |
19 | #include <QtCore/private/qglobal_p.h> |
20 | #include "qplatformdefs.h" |
21 | #include "QtCore/qatomic.h" |
22 | #include "QtCore/qdatetime.h" |
23 | #include "QtCore/qshareddata.h" |
24 | #include "QtCore/qtimezone.h" |
25 | |
26 | #if QT_CONFIG(timezone) |
27 | #include "qtimezone.h" |
28 | #endif |
29 | |
30 | #include <chrono> |
31 | |
32 | QT_BEGIN_NAMESPACE |
33 | |
34 | class QDateTimePrivate : public QSharedData |
35 | { |
36 | public: |
37 | // forward the declarations from QDateTime (this makes them public) |
38 | typedef QDateTime::ShortData QDateTimeShortData; |
39 | typedef QDateTime::Data QDateTimeData; |
40 | |
41 | // Never change or delete this enum, it is required for backwards compatible |
42 | // serialization of QDateTime before 5.2, so is essentially public API |
43 | enum Spec { |
44 | LocalUnknown = -1, |
45 | LocalStandard = 0, |
46 | LocalDST = 1, |
47 | UTC = 2, |
48 | OffsetFromUTC = 3, |
49 | TimeZone = 4 |
50 | }; |
51 | |
52 | // Daylight Time Status |
53 | enum DaylightStatus { |
54 | UnknownDaylightTime = -1, |
55 | StandardTime = 0, |
56 | DaylightTime = 1 |
57 | }; |
58 | |
59 | // Status of date/time |
60 | enum StatusFlag { |
61 | ShortData = 0x01, |
62 | |
63 | ValidDate = 0x02, |
64 | ValidTime = 0x04, |
65 | ValidDateTime = 0x08, |
66 | |
67 | TimeSpecMask = 0x30, |
68 | |
69 | SetToStandardTime = 0x40, |
70 | SetToDaylightTime = 0x80, |
71 | ValidityMask = ValidDate | ValidTime | ValidDateTime, |
72 | DaylightMask = SetToStandardTime | SetToDaylightTime, |
73 | }; |
74 | Q_DECLARE_FLAGS(StatusFlags, StatusFlag) |
75 | |
76 | |
77 | enum TransitionOption { |
78 | // Handling of a spring-forward (or other gap): |
79 | GapUseBefore = 2, |
80 | GapUseAfter = 4, |
81 | // Handling of a fall-back (or other repeated period): |
82 | FoldUseBefore = 0x20, |
83 | FoldUseAfter = 0x40, |
84 | // Quirk for negative DST: |
85 | FlipForReverseDst = 0x400, |
86 | |
87 | GapMask = GapUseBefore | GapUseAfter, |
88 | FoldMask = FoldUseBefore | FoldUseAfter, |
89 | }; |
90 | Q_DECLARE_FLAGS(TransitionOptions, TransitionOption) |
91 | |
92 | enum { |
93 | TimeSpecShift = 4, |
94 | }; |
95 | |
96 | struct ZoneState { |
97 | qint64 when; // ms after zone/local 1970 start; may be revised from the input time. |
98 | int offset = 0; // seconds |
99 | DaylightStatus dst = UnknownDaylightTime; |
100 | // Other fields are set, if possible, even when valid is false due to spring-forward. |
101 | bool valid = false; |
102 | |
103 | ZoneState(qint64 local) : when(local) {} |
104 | ZoneState(qint64 w, int o, DaylightStatus d, bool v = true) |
105 | : when(w), offset(o), dst(d), valid(v) {} |
106 | }; |
107 | |
108 | static QDateTime::Data create(QDate toDate, QTime toTime, const QTimeZone &timeZone, |
109 | QDateTime::TransitionResolution resolve); |
110 | #if QT_CONFIG(timezone) |
111 | static ZoneState zoneStateAtMillis(const QTimeZone &zone, qint64 millis, |
112 | TransitionOptions resolve); |
113 | #endif // timezone |
114 | |
115 | static ZoneState expressUtcAsLocal(qint64 utcMSecs); |
116 | |
117 | static ZoneState localStateAtMillis(qint64 millis, TransitionOptions resolve); |
118 | static QString localNameAtMillis(qint64 millis, DaylightStatus dst); // empty if unknown |
119 | |
120 | StatusFlags m_status = StatusFlag(Qt::LocalTime << TimeSpecShift); |
121 | qint64 m_msecs = 0; |
122 | int m_offsetFromUtc = 0; |
123 | QTimeZone m_timeZone; |
124 | }; |
125 | |
126 | Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::StatusFlags) |
127 | Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::TransitionOptions) |
128 | |
129 | namespace QtPrivate { |
130 | namespace DateTimeConstants { |
131 | using namespace std::chrono; |
132 | inline |
133 | constexpr qint64 SECS_PER_MIN = minutes::period::num; |
134 | inline |
135 | constexpr qint64 SECS_PER_HOUR = hours::period::num; |
136 | inline |
137 | constexpr qint64 SECS_PER_DAY = SECS_PER_HOUR * 24; // std::chrono::days is C++20 |
138 | |
139 | inline |
140 | constexpr qint64 MINS_PER_HOUR = std::ratio_divide<hours::period, minutes::period>::num; |
141 | |
142 | inline |
143 | constexpr qint64 MSECS_PER_SEC = milliseconds::period::den; |
144 | inline |
145 | constexpr qint64 MSECS_PER_MIN = SECS_PER_MIN * MSECS_PER_SEC; |
146 | inline |
147 | constexpr qint64 MSECS_PER_HOUR = SECS_PER_HOUR * MSECS_PER_SEC; |
148 | inline |
149 | constexpr qint64 MSECS_PER_DAY = SECS_PER_DAY * MSECS_PER_SEC; |
150 | |
151 | inline |
152 | constexpr qint64 JULIAN_DAY_FOR_EPOCH = 2440588; // result of QDate(1970, 1, 1).toJulianDay() |
153 | |
154 | inline |
155 | constexpr qint64 JulianDayMax = Q_INT64_C( 784354017364); |
156 | inline |
157 | constexpr qint64 JulianDayMin = Q_INT64_C(-784350574879); |
158 | } |
159 | } |
160 | |
161 | QT_END_NAMESPACE |
162 | |
163 | #endif // QDATETIME_P_H |
164 | |