Libosmium  2.15.4
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-2019 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 
37 #include <osmium/util/minmax.hpp> // IWYU pragma: keep
38 
39 #include <array>
40 #include <cassert>
41 #include <cstdint>
42 #include <ctime>
43 #include <iosfwd>
44 #include <limits>
45 #include <stdexcept>
46 #include <string>
47 #include <type_traits>
48 
49 namespace osmium {
50 
51  namespace detail {
52 
53  inline void add_2digit_int_to_string(int value, std::string& out) {
54  assert(value >= 0 && value <= 99);
55  if (value > 9) {
56  const int dec = value / 10;
57  out += static_cast<char>('0' + dec);
58  value -= dec * 10;
59  } else {
60  out += '0';
61  }
62  out += static_cast<char>('0' + value);
63  }
64 
65  inline void add_4digit_int_to_string(int value, std::string& out) {
66  assert(value >= 1000 && value <= 9999);
67 
68  const int dec1 = value / 1000;
69  out += static_cast<char>('0' + dec1);
70  value -= dec1 * 1000;
71 
72  const int dec2 = value / 100;
73  out += static_cast<char>('0' + dec2);
74  value -= dec2 * 100;
75 
76  const int dec3 = value / 10;
77  out += static_cast<char>('0' + dec3);
78  value -= dec3 * 10;
79 
80  out += static_cast<char>('0' + value);
81  }
82 
83  inline time_t parse_timestamp(const char* str) {
84  static const std::array<int, 12> mon_lengths = {{
85  31, 29, 31, 30, 31, 30,
86  31, 31, 30, 31, 30, 31
87  }};
88 
89  if (str[ 0] >= '0' && str[ 0] <= '9' &&
90  str[ 1] >= '0' && str[ 1] <= '9' &&
91  str[ 2] >= '0' && str[ 2] <= '9' &&
92  str[ 3] >= '0' && str[ 3] <= '9' &&
93  str[ 4] == '-' &&
94  str[ 5] >= '0' && str[ 5] <= '9' &&
95  str[ 6] >= '0' && str[ 6] <= '9' &&
96  str[ 7] == '-' &&
97  str[ 8] >= '0' && str[ 8] <= '9' &&
98  str[ 9] >= '0' && str[ 9] <= '9' &&
99  str[10] == 'T' &&
100  str[11] >= '0' && str[11] <= '9' &&
101  str[12] >= '0' && str[12] <= '9' &&
102  str[13] == ':' &&
103  str[14] >= '0' && str[14] <= '9' &&
104  str[15] >= '0' && str[15] <= '9' &&
105  str[16] == ':' &&
106  str[17] >= '0' && str[17] <= '9' &&
107  str[18] >= '0' && str[18] <= '9' &&
108  str[19] == 'Z') {
109  std::tm tm; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
110  tm.tm_year = (str[ 0] - '0') * 1000 +
111  (str[ 1] - '0') * 100 +
112  (str[ 2] - '0') * 10 +
113  (str[ 3] - '0') - 1900;
114  tm.tm_mon = (str[ 5] - '0') * 10 + (str[ 6] - '0') - 1;
115  tm.tm_mday = (str[ 8] - '0') * 10 + (str[ 9] - '0');
116  tm.tm_hour = (str[11] - '0') * 10 + (str[12] - '0');
117  tm.tm_min = (str[14] - '0') * 10 + (str[15] - '0');
118  tm.tm_sec = (str[17] - '0') * 10 + (str[18] - '0');
119  tm.tm_wday = 0;
120  tm.tm_yday = 0;
121  tm.tm_isdst = 0;
122  if (tm.tm_year >= 0 &&
123  tm.tm_mon >= 0 && tm.tm_mon <= 11 &&
124  tm.tm_mday >= 1 && tm.tm_mday <= mon_lengths[tm.tm_mon] &&
125  tm.tm_hour >= 0 && tm.tm_hour <= 23 &&
126  tm.tm_min >= 0 && tm.tm_min <= 59 &&
127  tm.tm_sec >= 0 && tm.tm_sec <= 60) {
128 #ifndef _WIN32
129  return timegm(&tm);
130 #else
131  return _mkgmtime(&tm);
132 #endif
133  }
134  }
135  throw std::invalid_argument{std::string{"can not parse timestamp: '"} + str + "'"};
136  }
137 
138  } // namespace detail
139 
147  class Timestamp {
148 
149  uint32_t m_timestamp = 0;
150 
151  void to_iso_str(std::string& s) const {
152  std::tm tm; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
153  time_t sse = seconds_since_epoch();
154 #ifndef NDEBUG
155  auto result =
156 #endif
157 #ifndef _WIN32
158  gmtime_r(&sse, &tm);
159  assert(result != nullptr);
160 #else
161  gmtime_s(&tm, &sse);
162  assert(result == 0);
163 #endif
164 
165  detail::add_4digit_int_to_string(tm.tm_year + 1900, s);
166  s += '-';
167  detail::add_2digit_int_to_string(tm.tm_mon + 1, s);
168  s += '-';
169  detail::add_2digit_int_to_string(tm.tm_mday, s);
170  s += 'T';
171  detail::add_2digit_int_to_string(tm.tm_hour, s);
172  s += ':';
173  detail::add_2digit_int_to_string(tm.tm_min, s);
174  s += ':';
175  detail::add_2digit_int_to_string(tm.tm_sec, s);
176  s += 'Z';
177  }
178 
179  public:
180 
184  constexpr Timestamp() noexcept = default;
185 
195  template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
196  constexpr Timestamp(T timestamp) noexcept : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
197  m_timestamp(uint32_t(timestamp)) {
198  }
199 
206  explicit Timestamp(const char* timestamp) {
207  m_timestamp = static_cast<uint32_t>(detail::parse_timestamp(timestamp));
208  }
209 
216  explicit Timestamp(const std::string& timestamp) :
217  Timestamp(timestamp.c_str()) {
218  }
219 
224  bool valid() const noexcept {
225  return m_timestamp != 0;
226  }
227 
229  explicit constexpr operator bool() const noexcept {
230  return m_timestamp != 0;
231  }
232 
234  constexpr time_t seconds_since_epoch() const noexcept {
235  return time_t(m_timestamp);
236  }
237 
239  explicit constexpr operator uint32_t() const noexcept {
240  return uint32_t(m_timestamp);
241  }
242 
244  explicit constexpr operator uint64_t() const noexcept {
245  return uint64_t(m_timestamp);
246  }
247 
253  OSMIUM_DEPRECATED constexpr operator time_t() const noexcept { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
254  return static_cast<time_t>(m_timestamp);
255  }
256 
257  template <typename T>
258  void operator+=(T time_difference) noexcept {
259  m_timestamp += time_difference;
260  }
261 
262  template <typename T>
263  void operator-=(T time_difference) noexcept {
264  m_timestamp -= time_difference;
265  }
266 
272  std::string to_iso() const {
273  std::string s;
274 
275  if (m_timestamp != 0) {
276  to_iso_str(s);
277  }
278 
279  return s;
280  }
281 
287  std::string to_iso_all() const {
288  std::string s;
289 
290  to_iso_str(s);
291 
292  return s;
293  }
294 
295  }; // class Timestamp
296 
301  inline constexpr Timestamp start_of_time() noexcept {
302  return {1};
303  }
304 
309  inline constexpr Timestamp end_of_time() noexcept {
310  return {std::numeric_limits<uint32_t>::max()};
311  }
312 
313  template <typename TChar, typename TTraits>
314  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, Timestamp timestamp) {
315  out << timestamp.to_iso();
316  return out;
317  }
318 
319  inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) noexcept {
320  return uint32_t(lhs) == uint32_t(rhs);
321  }
322 
323  inline bool operator!=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
324  return !(lhs == rhs);
325  }
326 
327  inline bool operator<(const Timestamp& lhs, const Timestamp& rhs) noexcept {
328  return uint32_t(lhs) < uint32_t(rhs);
329  }
330 
331  inline bool operator>(const Timestamp& lhs, const Timestamp& rhs) noexcept {
332  return rhs < lhs;
333  }
334 
335  inline bool operator<=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
336  return !(rhs < lhs);
337  }
338 
339  inline bool operator>=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
340  return !(lhs < rhs);
341  }
342 
343  template <>
344  inline osmium::Timestamp min_op_start_value<osmium::Timestamp>() {
345  return end_of_time();
346  }
347 
348  template <>
349  inline osmium::Timestamp max_op_start_value<osmium::Timestamp>() {
350  return start_of_time();
351  }
352 
353 } // namespace osmium
354 
355 #endif // OSMIUM_OSM_TIMESTAMP_HPP
#define OSMIUM_DEPRECATED
Definition: compatibility.hpp:51
type
Definition: entity_bits.hpp:63
bool operator<=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:461
constexpr Timestamp start_of_time() noexcept
Definition: timestamp.hpp:301
constexpr time_t seconds_since_epoch() const noexcept
Explicit conversion into time_t.
Definition: timestamp.hpp:234
void to_iso_str(std::string &s) const
Definition: timestamp.hpp:151
constexpr bool operator==(const Box &lhs, const Box &rhs) noexcept
Definition: box.hpp:212
bool valid() const noexcept
Definition: timestamp.hpp:224
std::string to_iso() const
Definition: timestamp.hpp:272
bool operator<(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:453
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
Definition: attr.hpp:333
Definition: timestamp.hpp:147
bool operator>=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:465
void operator-=(T time_difference) noexcept
Definition: timestamp.hpp:263
bool operator>(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:457
Timestamp(const std::string &timestamp)
Definition: timestamp.hpp:216
void operator+=(T time_difference) noexcept
Definition: timestamp.hpp:258
constexpr Timestamp(T timestamp) noexcept
Definition: timestamp.hpp:196
constexpr Timestamp end_of_time() noexcept
Definition: timestamp.hpp:309
Timestamp(const char *timestamp)
Definition: timestamp.hpp:206
bool operator!=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:446
std::string to_iso_all() const
Definition: timestamp.hpp:287