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 
6 This file is part of Osmium (https://osmcode.org/libosmium).
7 
8 Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS 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 
48 namespace 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