1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 **************************************************************************/
19 #ifndef REALM_TIMESTAMP_HPP
20 #define REALM_TIMESTAMP_HPP
24 #include <realm/util/assert.hpp>
25 #include <realm/null.hpp>
31 // Construct from the number of seconds and nanoseconds since the UNIX epoch: 00:00:00 UTC on 1 January 1970
33 // To split a native nanosecond representation, only division and modulo are necessary:
35 // s = native_nano / nanoseconds_per_second
36 // n = native_nano % nanoseconds_per_second
37 // Timestamp ts(s, n);
39 // To convert back into native nanosecond representation, simple multiply and add:
41 // native_nano = ts.s * nanoseconds_per_second + ts.n
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:
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)
65 Timestamp(int64_t seconds, int32_t nanoseconds)
67 , m_nanoseconds(nanoseconds)
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);
75 Timestamp(realm::null)
89 int64_t get_seconds() const noexcept
91 REALM_ASSERT(!m_is_null);
95 int32_t get_nanoseconds() const noexcept
97 REALM_ASSERT(!m_is_null);
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
108 if (is_null() && rhs.is_null())
111 if (is_null() != rhs.is_null())
114 return m_seconds == rhs.m_seconds && m_nanoseconds == rhs.m_nanoseconds;
116 bool operator!=(const Timestamp& rhs) const
118 return !(*this == rhs);
120 bool operator>(const Timestamp& rhs) const
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);
126 bool operator<(const Timestamp& rhs) const
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);
132 bool operator<=(const Timestamp& rhs) const
134 REALM_ASSERT(!is_null());
135 REALM_ASSERT(!rhs.is_null());
136 return *this < rhs || *this == rhs;
138 bool operator>=(const Timestamp& rhs) const
140 REALM_ASSERT(!is_null());
141 REALM_ASSERT(!rhs.is_null());
142 return *this > rhs || *this == rhs;
144 Timestamp& operator=(const Timestamp& rhs) = default;
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;
152 int32_t m_nanoseconds;
157 template <class C, class T>
158 inline std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& out, const Timestamp& d)
160 out << "Timestamp(" << d.m_seconds << ", " << d.m_nanoseconds << ")";
167 #endif // REALM_TIMESTAMP_HPP