summaryrefslogtreecommitdiffstats
path: root/src/corelib/time/qdatetime_p.h
blob: 02b047dd737e32aa12d30f201f595419e11253c1 (plain)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (C) 2022 The Qt Company Ltd.
// Copyright (C) 2016 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QDATETIME_P_H
#define QDATETIME_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include <QtCore/private/qglobal_p.h>
#include "qplatformdefs.h"
#include "QtCore/qatomic.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qshareddata.h"
#include "QtCore/qtimezone.h"

#if QT_CONFIG(timezone)
#include "qtimezone.h"
#endif

#include <chrono>

QT_BEGIN_NAMESPACE

class QDateTimePrivate : public QSharedData
{
public:
    // forward the declarations from QDateTime (this makes them public)
    typedef QDateTime::ShortData QDateTimeShortData;
    typedef QDateTime::Data QDateTimeData;

    // Never change or delete this enum, it is required for backwards compatible
    // serialization of QDateTime before 5.2, so is essentially public API
    enum Spec {
        LocalUnknown = -1,
        LocalStandard = 0,
        LocalDST = 1,
        UTC = 2,
        OffsetFromUTC = 3,
        TimeZone = 4
    };

    // Daylight Time Status
    enum DaylightStatus {
        UnknownDaylightTime = -1,
        StandardTime = 0,
        DaylightTime = 1
    };

    // Status of date/time
    enum StatusFlag {
        ShortData           = 0x01,

        ValidDate           = 0x02,
        ValidTime           = 0x04,
        ValidDateTime       = 0x08,

        TimeSpecMask        = 0x30,

        SetToStandardTime   = 0x40,
        SetToDaylightTime   = 0x80,
        ValidityMask        = ValidDate | ValidTime | ValidDateTime,
        DaylightMask        = SetToStandardTime | SetToDaylightTime,
    };
    Q_DECLARE_FLAGS(StatusFlags, StatusFlag)


    enum TransitionOption {
        // Handling of a spring-forward (or other gap):
        GapUseBefore = 2,
        GapUseAfter = 4,
        // Handling of a fall-back (or other repeated period):
        FoldUseBefore = 0x20,
        FoldUseAfter = 0x40,
        // Quirk for negative DST:
        FlipForReverseDst = 0x400,

        GapMask = GapUseBefore | GapUseAfter,
        FoldMask = FoldUseBefore | FoldUseAfter,
    };
    Q_DECLARE_FLAGS(TransitionOptions, TransitionOption)

    enum {
        TimeSpecShift = 4,
    };

    struct ZoneState {
        qint64 when; // ms after zone/local 1970 start; may be revised from the input time.
        int offset = 0; // seconds
        DaylightStatus dst = UnknownDaylightTime;
        // Other fields are set, if possible, even when valid is false due to spring-forward.
        bool valid = false;

        ZoneState(qint64 local) : when(local) {}
        ZoneState(qint64 w, int o, DaylightStatus d, bool v = true)
            : when(w), offset(o), dst(d), valid(v) {}
    };

    static QDateTime::Data create(QDate toDate, QTime toTime, const QTimeZone &timeZone,
                                  QDateTime::TransitionResolution resolve);
#if QT_CONFIG(timezone)
    static ZoneState zoneStateAtMillis(const QTimeZone &zone, qint64 millis,
                                       TransitionOptions resolve);
#endif // timezone

    static ZoneState expressUtcAsLocal(qint64 utcMSecs);

    static ZoneState localStateAtMillis(qint64 millis, TransitionOptions resolve);
    static QString localNameAtMillis(qint64 millis, DaylightStatus dst); // empty if unknown

    StatusFlags m_status = StatusFlag(Qt::LocalTime << TimeSpecShift);
    qint64 m_msecs = 0;
    int m_offsetFromUtc = 0;
    QTimeZone m_timeZone;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::StatusFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::TransitionOptions)

namespace QtPrivate {
namespace DateTimeConstants {
using namespace std::chrono;
constexpr qint64 SECS_PER_MIN = minutes::period::num;
constexpr qint64 SECS_PER_HOUR = hours::period::num;
constexpr qint64 SECS_PER_DAY = SECS_PER_HOUR * 24; // std::chrono::days is C++20

constexpr qint64 MINS_PER_HOUR = std::ratio_divide<hours::period, minutes::period>::num;

constexpr qint64 MSECS_PER_SEC = milliseconds::period::den;
constexpr qint64 MSECS_PER_MIN = SECS_PER_MIN * MSECS_PER_SEC;
constexpr qint64 MSECS_PER_HOUR = SECS_PER_HOUR * MSECS_PER_SEC;
constexpr qint64 MSECS_PER_DAY = SECS_PER_DAY * MSECS_PER_SEC;

constexpr qint64 JULIAN_DAY_FOR_EPOCH = 2440588; // result of QDate(1970, 1, 1).toJulianDay()

constexpr qint64 JulianDayMax = Q_INT64_C( 784354017364);
constexpr qint64 JulianDayMin = Q_INT64_C(-784350574879);
}
}

QT_END_NAMESPACE

#endif // QDATETIME_P_H