1 #ifndef OSMIUM_OSM_TIMESTAMP_HPP
2 #define OSMIUM_OSM_TIMESTAMP_HPP
47 #include <type_traits>
53 inline void add_2digit_int_to_string(
int value, std::string& out) {
54 assert(value >= 0 && value <= 99);
56 const int dec = value / 10;
57 out += static_cast<char>(
'0' + dec);
62 out += static_cast<char>(
'0' + value);
65 inline void add_4digit_int_to_string(
int value, std::string& out) {
66 assert(value >= 1000 && value <= 9999);
68 const int dec1 = value / 1000;
69 out += static_cast<char>(
'0' + dec1);
72 const int dec2 = value / 100;
73 out += static_cast<char>(
'0' + dec2);
76 const int dec3 = value / 10;
77 out += static_cast<char>(
'0' + dec3);
80 out += static_cast<char>(
'0' + value);
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
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' &&
94 str[ 5] >=
'0' && str[ 5] <=
'9' &&
95 str[ 6] >=
'0' && str[ 6] <=
'9' &&
97 str[ 8] >=
'0' && str[ 8] <=
'9' &&
98 str[ 9] >=
'0' && str[ 9] <=
'9' &&
100 str[11] >=
'0' && str[11] <=
'9' &&
101 str[12] >=
'0' && str[12] <=
'9' &&
103 str[14] >=
'0' && str[14] <=
'9' &&
104 str[15] >=
'0' && str[15] <=
'9' &&
106 str[17] >=
'0' && str[17] <=
'9' &&
107 str[18] >=
'0' && str[18] <=
'9' &&
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');
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) {
131 return _mkgmtime(&tm);
135 throw std::invalid_argument{std::string{
"can not parse timestamp: '"} + str +
"'"};
159 assert(result !=
nullptr);
165 detail::add_4digit_int_to_string(tm.tm_year + 1900, s);
167 detail::add_2digit_int_to_string(tm.tm_mon + 1, s);
169 detail::add_2digit_int_to_string(tm.tm_mday, s);
171 detail::add_2digit_int_to_string(tm.tm_hour, s);
173 detail::add_2digit_int_to_string(tm.tm_min, s);
175 detail::add_2digit_int_to_string(tm.tm_sec, s);
184 constexpr
Timestamp() noexcept = default;
195 template <typename T, typename
std::enable_if<
std::is_integral<T>::value,
int>::
type = 0>
207 m_timestamp = static_cast<uint32_t>(detail::parse_timestamp(timestamp));
229 explicit constexpr
operator bool() const noexcept {
239 explicit constexpr
operator uint32_t() const noexcept {
244 explicit constexpr
operator uint64_t() const noexcept {
257 template <
typename T>
262 template <
typename T>
310 return {std::numeric_limits<uint32_t>::max()};
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();
320 return uint32_t(lhs) == uint32_t(rhs);
324 return !(lhs == rhs);
328 return uint32_t(lhs) < uint32_t(rhs);
355 #endif // OSMIUM_OSM_TIMESTAMP_HPP