Libosmium  2.14.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 (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2018 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 <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 int mon_lengths[] = {
84  31, 29, 31, 30, 31, 30,
85  31, 31, 30, 31, 30, 31
86  };
87  if (str[ 0] >= '0' && str[ 0] <= '9' &&
88  str[ 1] >= '0' && str[ 1] <= '9' &&
89  str[ 2] >= '0' && str[ 2] <= '9' &&
90  str[ 3] >= '0' && str[ 3] <= '9' &&
91  str[ 4] == '-' &&
92  str[ 5] >= '0' && str[ 5] <= '9' &&
93  str[ 6] >= '0' && str[ 6] <= '9' &&
94  str[ 7] == '-' &&
95  str[ 8] >= '0' && str[ 8] <= '9' &&
96  str[ 9] >= '0' && str[ 9] <= '9' &&
97  str[10] == 'T' &&
98  str[11] >= '0' && str[11] <= '9' &&
99  str[12] >= '0' && str[12] <= '9' &&
100  str[13] == ':' &&
101  str[14] >= '0' && str[14] <= '9' &&
102  str[15] >= '0' && str[15] <= '9' &&
103  str[16] == ':' &&
104  str[17] >= '0' && str[17] <= '9' &&
105  str[18] >= '0' && str[18] <= '9' &&
106  str[19] == 'Z') {
107  struct tm tm;
108  tm.tm_year = (str[ 0] - '0') * 1000 +
109  (str[ 1] - '0') * 100 +
110  (str[ 2] - '0') * 10 +
111  (str[ 3] - '0') - 1900;
112  tm.tm_mon = (str[ 5] - '0') * 10 + (str[ 6] - '0') - 1;
113  tm.tm_mday = (str[ 8] - '0') * 10 + (str[ 9] - '0');
114  tm.tm_hour = (str[11] - '0') * 10 + (str[12] - '0');
115  tm.tm_min = (str[14] - '0') * 10 + (str[15] - '0');
116  tm.tm_sec = (str[17] - '0') * 10 + (str[18] - '0');
117  tm.tm_wday = 0;
118  tm.tm_yday = 0;
119  tm.tm_isdst = 0;
120  if (tm.tm_year >= 0 &&
121  tm.tm_mon >= 0 && tm.tm_mon <= 11 &&
122  tm.tm_mday >= 1 && tm.tm_mday <= mon_lengths[tm.tm_mon] &&
123  tm.tm_hour >= 0 && tm.tm_hour <= 23 &&
124  tm.tm_min >= 0 && tm.tm_min <= 59 &&
125  tm.tm_sec >= 0 && tm.tm_sec <= 60) {
126 #ifndef _WIN32
127  return timegm(&tm);
128 #else
129  return _mkgmtime(&tm);
130 #endif
131  }
132  }
133  throw std::invalid_argument{"can not parse timestamp"};
134  }
135 
136  } // namespace detail
137 
145  class Timestamp {
146 
147  uint32_t m_timestamp = 0;
148 
149  public:
150 
154  constexpr Timestamp() noexcept = default;
155 
165  template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
166  constexpr Timestamp(T timestamp) noexcept : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
167  m_timestamp(uint32_t(timestamp)) {
168  }
169 
176  explicit Timestamp(const char* timestamp) {
177  m_timestamp = static_cast<uint32_t>(detail::parse_timestamp(timestamp));
178  }
179 
186  explicit Timestamp(const std::string& timestamp) :
187  Timestamp(timestamp.c_str()) {
188  }
189 
194  bool valid() const noexcept {
195  return m_timestamp != 0;
196  }
197 
199  explicit constexpr operator bool() const noexcept {
200  return m_timestamp != 0;
201  }
202 
204  constexpr time_t seconds_since_epoch() const noexcept {
205  return time_t(m_timestamp);
206  }
207 
209  explicit constexpr operator uint32_t() const noexcept {
210  return uint32_t(m_timestamp);
211  }
212 
214  explicit constexpr operator uint64_t() const noexcept {
215  return uint64_t(m_timestamp);
216  }
217 
223  OSMIUM_DEPRECATED constexpr operator time_t() const noexcept { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
224  return static_cast<time_t>(m_timestamp);
225  }
226 
227  template <typename T>
228  void operator+=(T time_difference) noexcept {
229  m_timestamp += time_difference;
230  }
231 
232  template <typename T>
233  void operator-=(T time_difference) noexcept {
234  m_timestamp -= time_difference;
235  }
236 
242  std::string to_iso() const {
243  std::string s;
244 
245  if (m_timestamp != 0) {
246  struct tm tm;
247  time_t sse = seconds_since_epoch();
248 #ifndef NDEBUG
249  auto result =
250 #endif
251 #ifndef _WIN32
252  gmtime_r(&sse, &tm);
253  assert(result != nullptr);
254 #else
255  gmtime_s(&tm, &sse);
256  assert(result == 0);
257 #endif
258 
259  detail::add_4digit_int_to_string(tm.tm_year + 1900, s);
260  s += '-';
261  detail::add_2digit_int_to_string(tm.tm_mon + 1, s);
262  s += '-';
263  detail::add_2digit_int_to_string(tm.tm_mday, s);
264  s += 'T';
265  detail::add_2digit_int_to_string(tm.tm_hour, s);
266  s += ':';
267  detail::add_2digit_int_to_string(tm.tm_min, s);
268  s += ':';
269  detail::add_2digit_int_to_string(tm.tm_sec, s);
270  s += 'Z';
271  }
272 
273  return s;
274  }
275 
276  }; // class Timestamp
277 
282  inline constexpr Timestamp start_of_time() noexcept {
283  return {1};
284  }
285 
290  inline constexpr Timestamp end_of_time() noexcept {
291  return {std::numeric_limits<uint32_t>::max()};
292  }
293 
294  template <typename TChar, typename TTraits>
295  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, Timestamp timestamp) {
296  out << timestamp.to_iso();
297  return out;
298  }
299 
300  inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) noexcept {
301  return uint32_t(lhs) == uint32_t(rhs);
302  }
303 
304  inline bool operator!=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
305  return !(lhs == rhs);
306  }
307 
308  inline bool operator<(const Timestamp& lhs, const Timestamp& rhs) noexcept {
309  return uint32_t(lhs) < uint32_t(rhs);
310  }
311 
312  inline bool operator>(const Timestamp& lhs, const Timestamp& rhs) noexcept {
313  return rhs < lhs;
314  }
315 
316  inline bool operator<=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
317  return !(rhs < lhs);
318  }
319 
320  inline bool operator>=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
321  return !(lhs < rhs);
322  }
323 
324  template <>
325  inline osmium::Timestamp min_op_start_value<osmium::Timestamp>() {
326  return end_of_time();
327  }
328 
329  template <>
330  inline osmium::Timestamp max_op_start_value<osmium::Timestamp>() {
331  return start_of_time();
332  }
333 
334 } // namespace osmium
335 
336 #endif // OSMIUM_OSM_TIMESTAMP_HPP
#define OSMIUM_DEPRECATED
Definition: compatibility.hpp:50
type
Definition: entity_bits.hpp:63
bool operator<=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:456
constexpr Timestamp start_of_time() noexcept
Definition: timestamp.hpp:282
constexpr time_t seconds_since_epoch() const noexcept
Explicit conversion into time_t.
Definition: timestamp.hpp:204
constexpr bool operator==(const Box &lhs, const Box &rhs) noexcept
Definition: box.hpp:212
bool valid() const noexcept
Definition: timestamp.hpp:194
Definition: location.hpp:550
std::string to_iso() const
Definition: timestamp.hpp:242
bool operator<(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:448
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
Definition: attr.hpp:333
Definition: timestamp.hpp:145
bool operator>=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:460
void operator-=(T time_difference) noexcept
Definition: timestamp.hpp:233
bool operator>(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:452
Timestamp(const std::string &timestamp)
Definition: timestamp.hpp:186
void operator+=(T time_difference) noexcept
Definition: timestamp.hpp:228
constexpr Timestamp end_of_time() noexcept
Definition: timestamp.hpp:290
Timestamp(const char *timestamp)
Definition: timestamp.hpp:176
bool operator!=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:441