added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / timestamp.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_TIMESTAMP_HPP
20 #define REALM_TIMESTAMP_HPP
21
22 #include <cstdint>
23 #include <ostream>
24 #include <realm/util/assert.hpp>
25 #include <realm/null.hpp>
26
27 namespace realm {
28
29 class Timestamp {
30 public:
31     // Construct from the number of seconds and nanoseconds since the UNIX epoch: 00:00:00 UTC on 1 January 1970
32     //
33     // To split a native nanosecond representation, only division and modulo are necessary:
34     //
35     //     s = native_nano / nanoseconds_per_second
36     //     n = native_nano % nanoseconds_per_second
37     //     Timestamp ts(s, n);
38     //
39     // To convert back into native nanosecond representation, simple multiply and add:
40     //
41     //     native_nano = ts.s * nanoseconds_per_second + ts.n
42     //
43     // Specifically this allows the nanosecond part to become negative (only) for Timestamps before the UNIX epoch.
44     // Usually this will not need special attention, but for reference, valid Timestamps will have one of the
45     // following sign combinations:
46     //
47     //     s | n
48     //     -----
49     //     + | +
50     //     + | 0
51     //     0 | +
52     //     0 | 0
53     //     0 | -
54     //     - | 0
55     //     - | -
56     //
57     // Examples:
58     //     The UNIX epoch is constructed by Timestamp(0, 0)
59     //     Relative times are constructed as follows:
60     //       +1 second is constructed by Timestamp(1, 0)
61     //       +1 nanosecond is constructed by Timestamp(0, 1)
62     //       +1.1 seconds (1100 milliseconds after the epoch) is constructed by Timestamp(1, 100000000)
63     //       -1.1 seconds (1100 milliseconds before the epoch) is constructed by Timestamp(-1, -100000000)
64     //
65     Timestamp(int64_t seconds, int32_t nanoseconds)
66         : m_seconds(seconds)
67         , m_nanoseconds(nanoseconds)
68         , m_is_null(false)
69     {
70         REALM_ASSERT_EX(-nanoseconds_per_second < nanoseconds && nanoseconds < nanoseconds_per_second, nanoseconds);
71         const bool both_non_negative = seconds >= 0 && nanoseconds >= 0;
72         const bool both_non_positive = seconds <= 0 && nanoseconds <= 0;
73         REALM_ASSERT_EX(both_non_negative || both_non_positive, both_non_negative, both_non_positive);
74     }
75     Timestamp(realm::null)
76         : m_is_null(true)
77     {
78     }
79     Timestamp()
80         : Timestamp(null{})
81     {
82     }
83
84     bool is_null() const
85     {
86         return m_is_null;
87     }
88
89     int64_t get_seconds() const noexcept
90     {
91         REALM_ASSERT(!m_is_null);
92         return m_seconds;
93     }
94
95     int32_t get_nanoseconds() const noexcept
96     {
97         REALM_ASSERT(!m_is_null);
98         return m_nanoseconds;
99     }
100
101     // Note that only == and != operators work if one of the Timestamps are null! Else use realm::Greater,
102     // realm::Less, etc, instead. This is in order to collect all treatment of null behaviour in a single place for all
103     // types (query_conditions.hpp) to ensure that all types sort and compare null vs. non-null in the same manner,
104     // especially for int/float where we cannot override operators. This design is open for discussion, though,
105     // because it has usability drawbacks
106     bool operator==(const Timestamp& rhs) const
107     {
108         if (is_null() && rhs.is_null())
109             return true;
110
111         if (is_null() != rhs.is_null())
112             return false;
113
114         return m_seconds == rhs.m_seconds && m_nanoseconds == rhs.m_nanoseconds;
115     }
116     bool operator!=(const Timestamp& rhs) const
117     {
118         return !(*this == rhs);
119     }
120     bool operator>(const Timestamp& rhs) const
121     {
122         REALM_ASSERT(!is_null());
123         REALM_ASSERT(!rhs.is_null());
124         return (m_seconds > rhs.m_seconds) || (m_seconds == rhs.m_seconds && m_nanoseconds > rhs.m_nanoseconds);
125     }
126     bool operator<(const Timestamp& rhs) const
127     {
128         REALM_ASSERT(!is_null());
129         REALM_ASSERT(!rhs.is_null());
130         return (m_seconds < rhs.m_seconds) || (m_seconds == rhs.m_seconds && m_nanoseconds < rhs.m_nanoseconds);
131     }
132     bool operator<=(const Timestamp& rhs) const
133     {
134         REALM_ASSERT(!is_null());
135         REALM_ASSERT(!rhs.is_null());
136         return *this < rhs || *this == rhs;
137     }
138     bool operator>=(const Timestamp& rhs) const
139     {
140         REALM_ASSERT(!is_null());
141         REALM_ASSERT(!rhs.is_null());
142         return *this > rhs || *this == rhs;
143     }
144     Timestamp& operator=(const Timestamp& rhs) = default;
145
146     template <class Ch, class Tr>
147     friend std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& out, const Timestamp&);
148     static constexpr int32_t nanoseconds_per_second = 1000000000;
149
150 private:
151     int64_t m_seconds;
152     int32_t m_nanoseconds;
153     bool m_is_null;
154 };
155
156 // LCOV_EXCL_START
157 template <class C, class T>
158 inline std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& out, const Timestamp& d)
159 {
160     out << "Timestamp(" << d.m_seconds << ", " << d.m_nanoseconds << ")";
161     return out;
162 }
163 // LCOV_EXCL_STOP
164
165 } // namespace realm
166
167 #endif // REALM_TIMESTAMP_HPP