Libosmium  2.19.0
Fast and flexible C++ library for working with OpenStreetMap data
timestamp.hpp
Go to the documentation of this file.
1#ifndef OSMIUM_OSM_TIMESTAMP_HPP
2#define OSMIUM_OSM_TIMESTAMP_HPP
3
4/*
5
6This file is part of Osmium (https://osmcode.org/libosmium).
7
8Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
9
10Boost Software License - Version 1.0 - August 17th, 2003
11
12Permission is hereby granted, free of charge, to any person or organization
13obtaining a copy of the software and accompanying documentation covered by
14this license (the "Software") to use, reproduce, display, distribute,
15execute, and transmit the Software, and to prepare derivative works of the
16Software, and to permit third-parties to whom the Software is furnished to
17do so, all subject to the following:
18
19The copyright notices in the Software and this entire statement, including
20the above license grant, this restriction and the following disclaimer,
21must be included in all copies of the Software, in whole or in part, and
22all derivative works of the Software, unless such copies or derivative
23works are solely in the form of machine-executable object code generated by
24a source language processor.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32DEALINGS IN THE SOFTWARE.
33
34*/
35
36#include <osmium/util/minmax.hpp> // IWYU pragma: keep
37
38#include <array>
39#include <cassert>
40#include <cstdint>
41#include <ctime>
42#include <iosfwd>
43#include <limits>
44#include <stdexcept>
45#include <string>
46#include <type_traits>
47
48namespace osmium {
49
50 namespace detail {
51
52 inline void add_2digit_int_to_string(int value, std::string& out) {
53 assert(value >= 0 && value <= 99);
54 if (value > 9) {
55 const int dec = value / 10;
56 out += static_cast<char>('0' + dec);
57 value -= dec * 10;
58 } else {
59 out += '0';
60 }
61 out += static_cast<char>('0' + value);
62 }
63
64 inline void add_4digit_int_to_string(int value, std::string& out) {
65 assert(value >= 1000 && value <= 9999);
66
67 const int dec1 = value / 1000;
68 out += static_cast<char>('0' + dec1);
69 value -= dec1 * 1000;
70
71 const int dec2 = value / 100;
72 out += static_cast<char>('0' + dec2);
73 value -= dec2 * 100;
74
75 const int dec3 = value / 10;
76 out += static_cast<char>('0' + dec3);
77 value -= dec3 * 10;
78
79 out += static_cast<char>('0' + value);
80 }
81
82 inline time_t parse_timestamp(const char* str) {
83 static const std::array<int, 12> mon_lengths = {{
84 31, 29, 31, 30, 31, 30,
85 31, 31, 30, 31, 30, 31
86 }};
87
88 if (str[ 0] >= '0' && str[ 0] <= '9' &&
89 str[ 1] >= '0' && str[ 1] <= '9' &&
90 str[ 2] >= '0' && str[ 2] <= '9' &&
91 str[ 3] >= '0' && str[ 3] <= '9' &&
92 str[ 4] == '-' &&
93 str[ 5] >= '0' && str[ 5] <= '9' &&
94 str[ 6] >= '0' && str[ 6] <= '9' &&
95 str[ 7] == '-' &&
96 str[ 8] >= '0' && str[ 8] <= '9' &&
97 str[ 9] >= '0' && str[ 9] <= '9' &&
98 str[10] == 'T' &&
99 str[11] >= '0' && str[11] <= '9' &&
100 str[12] >= '0' && str[12] <= '9' &&
101 str[13] == ':' &&
102 str[14] >= '0' && str[14] <= '9' &&
103 str[15] >= '0' && str[15] <= '9' &&
104 str[16] == ':' &&
105 str[17] >= '0' && str[17] <= '9' &&
106 str[18] >= '0' && str[18] <= '9' &&
107 str[19] == 'Z') {
108 std::tm tm; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
109 tm.tm_year = (str[ 0] - '0') * 1000 +
110 (str[ 1] - '0') * 100 +
111 (str[ 2] - '0') * 10 +
112 (str[ 3] - '0') - 1900;
113 tm.tm_mon = (str[ 5] - '0') * 10 + (str[ 6] - '0') - 1;
114 tm.tm_mday = (str[ 8] - '0') * 10 + (str[ 9] - '0');
115 tm.tm_hour = (str[11] - '0') * 10 + (str[12] - '0');
116 tm.tm_min = (str[14] - '0') * 10 + (str[15] - '0');
117 tm.tm_sec = (str[17] - '0') * 10 + (str[18] - '0');
118 tm.tm_wday = 0;
119 tm.tm_yday = 0;
120 tm.tm_isdst = 0;
121 if (tm.tm_year >= 0 &&
122 tm.tm_mon >= 0 && tm.tm_mon <= 11 &&
123 tm.tm_mday >= 1 && tm.tm_mday <= mon_lengths[tm.tm_mon] &&
124 tm.tm_hour >= 0 && tm.tm_hour <= 23 &&
125 tm.tm_min >= 0 && tm.tm_min <= 59 &&
126 tm.tm_sec >= 0 && tm.tm_sec <= 60) {
127#ifndef _WIN32
128 return timegm(&tm);
129#else
130 return _mkgmtime(&tm);
131#endif
132 }
133 }
134 throw std::invalid_argument{std::string{"can not parse timestamp: '"} + str + "'"};
135 }
136
137 } // namespace detail
138
146 class Timestamp {
147
148 uint32_t m_timestamp = 0;
149
150 void to_iso_str(std::string& s) const {
151 std::tm tm; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
152 time_t sse = seconds_since_epoch();
153#ifndef NDEBUG
154 auto result =
155#endif
156#ifndef _WIN32
157 gmtime_r(&sse, &tm);
158 assert(result != nullptr);
159#else
160 gmtime_s(&tm, &sse);
161 assert(result == 0);
162#endif
163
164 detail::add_4digit_int_to_string(tm.tm_year + 1900, s);
165 s += '-';
166 detail::add_2digit_int_to_string(tm.tm_mon + 1, s);
167 s += '-';
168 detail::add_2digit_int_to_string(tm.tm_mday, s);
169 s += 'T';
170 detail::add_2digit_int_to_string(tm.tm_hour, s);
171 s += ':';
172 detail::add_2digit_int_to_string(tm.tm_min, s);
173 s += ':';
174 detail::add_2digit_int_to_string(tm.tm_sec, s);
175 s += 'Z';
176 }
177
178 public:
179
183 constexpr Timestamp() noexcept = default;
184
194 template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
195 constexpr Timestamp(T timestamp) noexcept : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
196 m_timestamp(uint32_t(timestamp)) {
197 }
198
205 explicit Timestamp(const char* timestamp) :
206 m_timestamp(static_cast<uint32_t>(detail::parse_timestamp(timestamp))) {
207 }
208
215 explicit Timestamp(const std::string& timestamp) :
216 Timestamp(timestamp.c_str()) {
217 }
218
223 bool valid() const noexcept {
224 return m_timestamp != 0;
225 }
226
228 explicit constexpr operator bool() const noexcept {
229 return m_timestamp != 0;
230 }
231
233 constexpr time_t seconds_since_epoch() const noexcept {
234 return time_t(m_timestamp);
235 }
236
238 explicit constexpr operator uint32_t() const noexcept {
239 return uint32_t(m_timestamp);
240 }
241
243 explicit constexpr operator uint64_t() const noexcept {
244 return uint64_t(m_timestamp);
245 }
246
247 template <typename T>
248 void operator+=(T time_difference) noexcept {
249 m_timestamp += time_difference;
250 }
251
252 template <typename T>
253 void operator-=(T time_difference) noexcept {
254 m_timestamp -= time_difference;
255 }
256
262 std::string to_iso() const {
263 std::string s;
264
265 if (m_timestamp != 0) {
266 to_iso_str(s);
267 }
268
269 return s;
270 }
271
277 std::string to_iso_all() const {
278 std::string s;
279
280 to_iso_str(s);
281
282 return s;
283 }
284
285 }; // class Timestamp
286
291 inline constexpr Timestamp start_of_time() noexcept {
292 return {1};
293 }
294
299 inline constexpr Timestamp end_of_time() noexcept {
300 return {std::numeric_limits<uint32_t>::max()};
301 }
302
303 template <typename TChar, typename TTraits>
304 inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, Timestamp timestamp) {
305 out << timestamp.to_iso();
306 return out;
307 }
308
309 inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) noexcept {
310 return uint32_t(lhs) == uint32_t(rhs);
311 }
312
313 inline bool operator!=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
314 return !(lhs == rhs);
315 }
316
317 inline bool operator<(const Timestamp& lhs, const Timestamp& rhs) noexcept {
318 return uint32_t(lhs) < uint32_t(rhs);
319 }
320
321 inline bool operator>(const Timestamp& lhs, const Timestamp& rhs) noexcept {
322 return rhs < lhs;
323 }
324
325 inline bool operator<=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
326 return !(rhs < lhs);
327 }
328
329 inline bool operator>=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
330 return !(lhs < rhs);
331 }
332
333 template <>
334 inline osmium::Timestamp min_op_start_value<osmium::Timestamp>() {
335 return end_of_time();
336 }
337
338 template <>
339 inline osmium::Timestamp max_op_start_value<osmium::Timestamp>() {
340 return start_of_time();
341 }
342
343} // namespace osmium
344
345#endif // OSMIUM_OSM_TIMESTAMP_HPP
Definition: timestamp.hpp:146
void to_iso_str(std::string &s) const
Definition: timestamp.hpp:150
std::string to_iso() const
Definition: timestamp.hpp:262
constexpr time_t seconds_since_epoch() const noexcept
Explicit conversion into time_t.
Definition: timestamp.hpp:233
Timestamp(const std::string &timestamp)
Definition: timestamp.hpp:215
constexpr Timestamp() noexcept=default
uint32_t m_timestamp
Definition: timestamp.hpp:148
bool valid() const noexcept
Definition: timestamp.hpp:223
void operator+=(T time_difference) noexcept
Definition: timestamp.hpp:248
void operator-=(T time_difference) noexcept
Definition: timestamp.hpp:253
Timestamp(const char *timestamp)
Definition: timestamp.hpp:205
std::string to_iso_all() const
Definition: timestamp.hpp:277
Definition: attr.hpp:342
type
Definition: entity_bits.hpp:63
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
constexpr Timestamp end_of_time() noexcept
Definition: timestamp.hpp:299
bool operator==(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:440
bool operator<=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:459
bool operator>(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:455
bool operator>=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:463
bool operator!=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:444
constexpr Timestamp start_of_time() noexcept
Definition: timestamp.hpp:291
std::basic_ostream< TChar, TTraits > & operator<<(std::basic_ostream< TChar, TTraits > &out, const item_type item_type)
Definition: item_type.hpp:187
bool operator<(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:451
Definition: location.hpp:555