Libosmium  2.13.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-2017 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 <cassert>
37 #include <cstdint>
38 #include <ctime>
39 #include <iosfwd>
40 #include <limits>
41 #include <stdexcept>
42 #include <string>
43 #include <type_traits>
44 
46 #include <osmium/util/minmax.hpp> // IWYU pragma: keep
47 
48 namespace osmium {
49 
50  namespace detail {
51 
52  inline time_t parse_timestamp(const char* str) {
53  static const int mon_lengths[] = {
54  31, 29, 31, 30, 31, 30,
55  31, 31, 30, 31, 30, 31
56  };
57  if (str[ 0] >= '0' && str[ 0] <= '9' &&
58  str[ 1] >= '0' && str[ 1] <= '9' &&
59  str[ 2] >= '0' && str[ 2] <= '9' &&
60  str[ 3] >= '0' && str[ 3] <= '9' &&
61  str[ 4] == '-' &&
62  str[ 5] >= '0' && str[ 5] <= '9' &&
63  str[ 6] >= '0' && str[ 6] <= '9' &&
64  str[ 7] == '-' &&
65  str[ 8] >= '0' && str[ 8] <= '9' &&
66  str[ 9] >= '0' && str[ 9] <= '9' &&
67  str[10] == 'T' &&
68  str[11] >= '0' && str[11] <= '9' &&
69  str[12] >= '0' && str[12] <= '9' &&
70  str[13] == ':' &&
71  str[14] >= '0' && str[14] <= '9' &&
72  str[15] >= '0' && str[15] <= '9' &&
73  str[16] == ':' &&
74  str[17] >= '0' && str[17] <= '9' &&
75  str[18] >= '0' && str[18] <= '9' &&
76  str[19] == 'Z') {
77  struct tm tm;
78  tm.tm_year = (str[ 0] - '0') * 1000 +
79  (str[ 1] - '0') * 100 +
80  (str[ 2] - '0') * 10 +
81  (str[ 3] - '0') - 1900;
82  tm.tm_mon = (str[ 5] - '0') * 10 + (str[ 6] - '0') - 1;
83  tm.tm_mday = (str[ 8] - '0') * 10 + (str[ 9] - '0');
84  tm.tm_hour = (str[11] - '0') * 10 + (str[12] - '0');
85  tm.tm_min = (str[14] - '0') * 10 + (str[15] - '0');
86  tm.tm_sec = (str[17] - '0') * 10 + (str[18] - '0');
87  tm.tm_wday = 0;
88  tm.tm_yday = 0;
89  tm.tm_isdst = 0;
90  if (tm.tm_year >= 0 &&
91  tm.tm_mon >= 0 && tm.tm_mon <= 11 &&
92  tm.tm_mday >= 1 && tm.tm_mday <= mon_lengths[tm.tm_mon] &&
93  tm.tm_hour >= 0 && tm.tm_hour <= 23 &&
94  tm.tm_min >= 0 && tm.tm_min <= 59 &&
95  tm.tm_sec >= 0 && tm.tm_sec <= 60) {
96 #ifndef _WIN32
97  return timegm(&tm);
98 #else
99  return _mkgmtime(&tm);
100 #endif
101  }
102  }
103  throw std::invalid_argument{"can not parse timestamp"};
104  }
105 
106  } // namespace detail
107 
115  class Timestamp {
116 
117  // length of ISO timestamp string yyyy-mm-ddThh:mm:ssZ\0
118  static constexpr const int timestamp_length = 20 + 1;
119 
120  // The timestamp format for OSM timestamps in strftime(3) format.
121  // This is the ISO-Format "yyyy-mm-ddThh:mm:ssZ".
122  static const char* timestamp_format() {
123  static const char f[timestamp_length] = "%Y-%m-%dT%H:%M:%SZ";
124  return f;
125  }
126 
127  uint32_t m_timestamp;
128 
129  public:
130 
134  constexpr Timestamp() noexcept :
135  m_timestamp(0) {
136  }
137 
147  template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
148  constexpr Timestamp(T timestamp) noexcept :
149  m_timestamp(uint32_t(timestamp)) {
150  }
151 
158  explicit Timestamp(const char* timestamp) {
159  m_timestamp = static_cast<uint32_t>(detail::parse_timestamp(timestamp));
160  }
161 
168  explicit Timestamp(const std::string& timestamp) :
169  Timestamp(timestamp.c_str()) {
170  }
171 
176  bool valid() const noexcept {
177  return m_timestamp != 0;
178  }
179 
181  explicit constexpr operator bool() const noexcept {
182  return m_timestamp != 0;
183  }
184 
186  constexpr time_t seconds_since_epoch() const noexcept {
187  return time_t(m_timestamp);
188  }
189 
191  explicit constexpr operator uint32_t() const noexcept {
192  return uint32_t(m_timestamp);
193  }
194 
196  explicit constexpr operator uint64_t() const noexcept {
197  return uint64_t(m_timestamp);
198  }
199 
205  OSMIUM_DEPRECATED constexpr operator time_t() const noexcept {
206  return static_cast<time_t>(m_timestamp);
207  }
208 
209  template <typename T>
210  void operator+=(T time_difference) noexcept {
211  m_timestamp += time_difference;
212  }
213 
214  template <typename T>
215  void operator-=(T time_difference) noexcept {
216  m_timestamp -= time_difference;
217  }
218 
224  std::string to_iso() const {
225  std::string s;
226 
227  if (m_timestamp != 0) {
228  struct tm tm;
229  time_t sse = seconds_since_epoch();
230 #ifndef NDEBUG
231  auto result =
232 #endif
233 #ifndef _MSC_VER
234  gmtime_r(&sse, &tm);
235  assert(result != nullptr);
236 #else
237  gmtime_s(&tm, &sse);
238  assert(result == 0);
239 #endif
240 
241  s.resize(timestamp_length);
242  /* This const_cast is ok, because we know we have enough space
243  in the string for the format we are using (well at least until
244  the year will have 5 digits). And by setting the size
245  afterwards from the result of strftime we make sure thats set
246  right, too. */
247  s.resize(strftime(const_cast<char*>(s.c_str()), timestamp_length, timestamp_format(), &tm));
248  }
249 
250  return s;
251  }
252 
253  }; // class Timestamp
254 
259  inline constexpr Timestamp start_of_time() noexcept {
260  return Timestamp(1);
261  }
262 
267  inline constexpr Timestamp end_of_time() noexcept {
268  return Timestamp(std::numeric_limits<uint32_t>::max());
269  }
270 
271  template <typename TChar, typename TTraits>
272  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, Timestamp timestamp) {
273  out << timestamp.to_iso();
274  return out;
275  }
276 
277  inline bool operator==(const Timestamp& lhs, const Timestamp& rhs) noexcept {
278  return uint32_t(lhs) == uint32_t(rhs);
279  }
280 
281  inline bool operator!=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
282  return !(lhs == rhs);
283  }
284 
285  inline bool operator<(const Timestamp& lhs, const Timestamp& rhs) noexcept {
286  return uint32_t(lhs) < uint32_t(rhs);
287  }
288 
289  inline bool operator>(const Timestamp& lhs, const Timestamp& rhs) noexcept {
290  return rhs < lhs;
291  }
292 
293  inline bool operator<=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
294  return ! (rhs < lhs);
295  }
296 
297  inline bool operator>=(const Timestamp& lhs, const Timestamp& rhs) noexcept {
298  return ! (lhs < rhs);
299  }
300 
301  template <>
302  inline osmium::Timestamp min_op_start_value<osmium::Timestamp>() {
303  return end_of_time();
304  }
305 
306  template <>
307  inline osmium::Timestamp max_op_start_value<osmium::Timestamp>() {
308  return start_of_time();
309  }
310 
311 } // namespace osmium
312 
313 #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:455
constexpr Timestamp start_of_time() noexcept
Definition: timestamp.hpp:259
constexpr time_t seconds_since_epoch() const noexcept
Explicit conversion into time_t.
Definition: timestamp.hpp:186
constexpr bool operator==(const Box &lhs, const Box &rhs) noexcept
Definition: box.hpp:221
bool valid() const noexcept
Definition: timestamp.hpp:176
std::string to_iso() const
Definition: timestamp.hpp:224
bool operator<(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:447
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
Definition: attr.hpp:333
Definition: timestamp.hpp:115
bool operator>=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:459
void operator-=(T time_difference) noexcept
Definition: timestamp.hpp:215
bool operator>(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:451
constexpr Timestamp() noexcept
Definition: timestamp.hpp:134
Timestamp(const std::string &timestamp)
Definition: timestamp.hpp:168
void operator+=(T time_difference) noexcept
Definition: timestamp.hpp:210
constexpr Timestamp(T timestamp) noexcept
Definition: timestamp.hpp:148
constexpr Timestamp end_of_time() noexcept
Definition: timestamp.hpp:267
Timestamp(const char *timestamp)
Definition: timestamp.hpp:158
uint32_t m_timestamp
Definition: timestamp.hpp:127
bool operator!=(const Changeset &lhs, const Changeset &rhs)
Definition: changeset.hpp:440
static const char * timestamp_format()
Definition: timestamp.hpp:122