16#include <daw/daw_arith_traits.h>
17#include <daw/daw_cpp_feature_check.h>
18#include <daw/daw_string_view.h>
19#include <daw/daw_traits.h>
20#include <daw/daw_uint_buffer.h>
28 namespace parse_utils {
29 template<
typename Result, std::
size_t count>
31 UInt64 result = UInt64( );
32 for( std::size_t
n = 0;
n < count; ++
n ) {
36 return static_cast<Result
>( result );
39 template<
typename Result>
41 UInt64 result = UInt64( );
49 return static_cast<Result
>( result );
58 namespace datetime_details {
60 template<
typename Result,
typename Bounds, std::ptrdiff_t Ex>
63 static_assert( daw::numeric_limits<Result>::digits10 >= 4 );
67 if( sv.front( ) ==
'-' ) {
68 if constexpr( daw::is_signed_v<Result> ) {
72 }
else if( sv.front( ) ==
'+' ) {
75 while( not sv.empty( ) ) {
79 result +=
static_cast<Result
>( dig );
86 template<
typename Clock = std::chrono::system_clock,
87 typename Duration = std::chrono::milliseconds>
88 constexpr std::chrono::time_point<Clock, Duration>
90 std::uint_least32_t dy, std::uint_least32_t hr,
91 std::uint_least32_t mn, std::uint_least32_t se,
92 std::uint_least32_t ms ) {
93 constexpr auto calc = []( std::int_least32_t y, std::uint_least32_t m,
94 std::uint_least32_t d, std::uint_least32_t h,
95 std::uint_least32_t min,
96 std::uint_least32_t s,
97 std::uint_least32_t mil ) {
98 y -=
static_cast<std::int_least32_t
>( m ) <= 2;
99 std::int_least32_t
const era = ( y >= 0 ? y : y - 399 ) / 400;
100 auto const yoe =
static_cast<std::uint_least32_t
>(
101 static_cast<std::int_least32_t
>( y ) - era * 400 );
102 auto const doy =
static_cast<std::uint_least32_t
>(
103 ( 153 * (
static_cast<std::int_least32_t
>( m ) +
104 (
static_cast<std::int_least32_t
>( m ) > 2 ? -3 : 9 ) ) +
107 static_cast<std::int_least32_t
>( d ) - 1 );
108 std::uint_least32_t
const doe =
109 yoe * 365 + yoe / 4 - yoe / 100 + doy;
110 std::int_least32_t
const days_since_epoch =
111 era * 146097 +
static_cast<std::int_least32_t
>( doe ) - 719468;
114 std::chrono::duration<std::int_least32_t, std::ratio<86400>>;
115 return std::chrono::time_point<std::chrono::system_clock,
116 std::chrono::milliseconds>{ } +
117 ( Days( days_since_epoch ) + std::chrono::hours( h ) +
118 std::chrono::minutes( min ) +
119 std::chrono::seconds(
120 static_cast<std::uint_least32_t
>( s ) ) +
121 std::chrono::milliseconds( mil ) );
128 auto result = calc( yr, mo, dy, hr, mn, se, ms );
130 if constexpr( std::conjunction_v<
131 std::is_same<Duration, std::chrono::milliseconds>,
132 std::is_same<Clock, std::chrono::system_clock>> ) {
134 }
else if constexpr( std::is_same_v<Clock,
135 std::chrono::system_clock> ) {
136 return std::chrono::duration_cast<Duration>( result );
138#if defined( __cpp_lib_chrono ) and __cpp_lib_chrono >= 201907
140 auto const match_duration =
141 std::chrono::time_point_cast<Duration>( result );
142 auto const match_clock =
143 std::chrono::clock_cast<Clock>( match_duration );
149 auto const system_epoch = std::chrono::floor<std::chrono::hours>(
150 std::chrono::system_clock::now( ).time_since_epoch( ) +
151 std::chrono::minutes( 30 ) );
152 auto const clock_epoch = std::chrono::floor<std::chrono::hours>(
153 Clock::now( ).time_since_epoch( ) + std::chrono::minutes( 30 ) );
155 constexpr auto offset =
156 std::chrono::duration_cast<std::chrono::milliseconds>(
157 clock_epoch - system_epoch );
158 return std::chrono::duration_cast<Duration>( result + offset );
169 template<
typename Bounds, std::ptrdiff_t Ex>
171 daw::basic_string_view<char, Bounds, Ex> timestamp_str ) {
173 result.
day = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
174 std::data( timestamp_str.pop_back( 2U ) ) );
176 timestamp_str.remove_suffix( );
178 result.month = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
179 std::data( timestamp_str.pop_back( 2U ) ) );
181 timestamp_str.remove_suffix( );
184 datetime_details::parse_number<std::int_least32_t>( timestamp_str );
195 template<
typename Bounds, std::ptrdiff_t Ex>
197 daw::basic_string_view<char, Bounds, Ex> timestamp_str ) {
199 result.
hour = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
200 std::data( timestamp_str.pop_front( 2 ) ) );
202 timestamp_str.remove_prefix( );
204 result.minute = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
205 std::data( timestamp_str.pop_front( 2 ) ) );
206 if( timestamp_str.empty( ) ) {
210 timestamp_str.remove_prefix( );
212 result.second = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
213 std::data( timestamp_str.pop_front( 2 ) ) );
214 if( timestamp_str.empty( ) ) {
218 timestamp_str.remove_prefix( );
221 datetime_details::parse_number<std::uint_least32_t>(
222 timestamp_str.pop_front( 3 ) );
226 template<
typename Bounds, std::ptrdiff_t Ex>
227 constexpr std::chrono::time_point<std::chrono::system_clock,
228 std::chrono::milliseconds>
230 constexpr daw::string_view t_str =
"T";
231 auto const date_str = ts.pop_front( t_str );
234 ErrorReason::InvalidTimestamp );
239 auto time_str = ts.pop_front( [](
char c ) {
245 if( not( ts.empty( ) or ts.front( ) ==
'Z' ) ) {
247 ErrorReason::InvalidTimestamp );
249 bool const sign = ts.front( ) ==
'+';
251 auto hr_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
253 if( ts.front( ) ==
':' ) {
256 auto mn_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
261 hms.
hour -= hr_offset;
265 hms.
hour += hr_offset;
282 template<
typename Clock,
typename Duration>
284 std::chrono::time_point<Clock, Duration>
const &tp ) {
285 auto dur_from_epoch = tp.time_since_epoch( );
287 std::chrono::duration<std::int_least32_t, std::ratio<86400>>;
288 auto const days_since_epoch =
289 std::chrono::duration_cast<Days>( dur_from_epoch );
290 std::int_least32_t z = days_since_epoch.count( );
292 std::int_least32_t
const era = ( z >= 0 ? z : z - 146096 ) / 146097;
294 static_cast<std::uint_least32_t
>( z - era * 146097 );
295 std::uint_least32_t
const yoe =
296 ( doe - doe / 1460 + doe / 36524 - doe / 146096 ) / 365;
297 std::int_least32_t
const y =
298 static_cast<std::int_least32_t
>( yoe ) + era * 400;
299 std::uint_least32_t
const doy =
300 doe - ( 365 * yoe + yoe / 4 - yoe / 100 );
301 std::uint_least32_t
const mp = ( 5 * doy + 2 ) / 153;
302 std::uint_least32_t
const d = doy - ( 153 * mp + 2 ) / 5 + 1;
303 auto const m =
static_cast<std::uint_least32_t
>(
304 static_cast<std::int_least32_t
>( mp ) +
305 (
static_cast<std::int_least32_t
>( mp ) < 10 ? 3 : -9 ) );
307 dur_from_epoch -= days_since_epoch;
309 std::chrono::duration_cast<std::chrono::hours>( dur_from_epoch );
310 dur_from_epoch -= hrs;
312 std::chrono::duration_cast<std::chrono::minutes>( dur_from_epoch );
313 dur_from_epoch -= min;
315 std::chrono::duration_cast<std::chrono::seconds>( dur_from_epoch );
316 dur_from_epoch -= sec;
317 auto const ms = std::chrono::duration_cast<std::chrono::milliseconds>(
319 return ymdhms{ y + ( m <= 2 ),
322 static_cast<std::uint_least32_t
>( hrs.count( ) ),
323 static_cast<std::uint_least32_t
>( min.count( ) ),
324 static_cast<std::uint_least32_t
>( sec.count( ) ),
325 static_cast<std::uint_least32_t
>( ms.count( ) ) };
361 template<
typename Duration>
363 std::chrono::time_point<std::chrono::system_clock, Duration> tp ) {
364 using days = std::chrono::duration<long, std::ratio<86400>>;
366 std::chrono::duration_cast<days>( tp.time_since_epoch( ) ).count( );
367 auto const dow = z >= -4L ? ( z + 4L ) % 7L : ( z + 5L ) % 7L + 6L;
389 std::chrono::time_point<std::chrono::system_clock,
390 std::chrono::milliseconds>( ) ) ==
"Thu" );
392 namespace datetime_details {
393 constexpr std::uint_least32_t
month2num( std::string_view ts ) {
395 ErrorReason::InvalidTimestamp );
396 auto const b0 =
static_cast<std::uint_least32_t
>(
397 static_cast<unsigned char>( ts[0] ) );
398 auto const b1 =
static_cast<std::uint_least32_t
>(
399 static_cast<unsigned char>( ts[1] ) );
400 auto const b2 =
static_cast<std::uint_least32_t
>(
401 static_cast<unsigned char>( ts[2] ) );
402 return ( b0 << 16U ) | ( b1 << 8U ) | b2;
#define daw_json_assert(Bool,...)
Definition: daw_json_assert.h:179
constexpr Result parse_number(daw::basic_string_view< char, Bounds, Ex > sv)
Definition: daw_json_parse_iso8601_utils.h:62
constexpr std::uint_least32_t month2num(std::string_view ts)
Definition: daw_json_parse_iso8601_utils.h:393
constexpr time_parts parse_iso_8601_time(daw::basic_string_view< char, Bounds, Ex > timestamp_str)
Definition: daw_json_parse_iso8601_utils.h:196
constexpr date_parts parse_iso_8601_date(daw::basic_string_view< char, Bounds, Ex > timestamp_str)
Definition: daw_json_parse_iso8601_utils.h:170
constexpr unsigned parse_short_month(std::string_view ts)
Definition: daw_json_parse_iso8601_utils.h:406
constexpr ymdhms time_point_to_civil(std::chrono::time_point< Clock, Duration > const &tp)
Definition: daw_json_parse_iso8601_utils.h:283
constexpr std::string_view short_day_of_week(std::chrono::time_point< std::chrono::system_clock, Duration > tp)
Definition: daw_json_parse_iso8601_utils.h:362
constexpr std::chrono::time_point< Clock, Duration > civil_to_time_point(std::int_least32_t yr, std::uint_least32_t mo, std::uint_least32_t dy, std::uint_least32_t hr, std::uint_least32_t mn, std::uint_least32_t se, std::uint_least32_t ms)
Definition: daw_json_parse_iso8601_utils.h:89
constexpr std::chrono::time_point< std::chrono::system_clock, std::chrono::milliseconds > parse_iso8601_timestamp(daw::basic_string_view< char, Bounds, Ex > ts)
Definition: daw_json_parse_iso8601_utils.h:229
constexpr std::string_view month_short_name(unsigned m)
Definition: daw_json_parse_iso8601_utils.h:328
static constexpr DAW_ATTRIB_FLATINLINE unsigned parse_digit(char c)
Definition: daw_json_parse_digit.h:19
constexpr Result parse_unsigned2(char const *digit_str)
Definition: daw_json_parse_iso8601_utils.h:40
constexpr Result parse_unsigned(char const *digit_str)
Definition: daw_json_parse_iso8601_utils.h:30
constexpr bool is_number(char c)
Definition: daw_json_parse_iso8601_utils.h:52
DAW_ATTRIB_NOINLINE void daw_json_error(ErrorReason reason)
Definition: daw_json_assert.h:39
Definition: daw_from_json.h:22
Definition: daw_json_parse_iso8601_utils.h:163
uint_least32_t month
Definition: daw_json_parse_iso8601_utils.h:165
uint_least32_t day
Definition: daw_json_parse_iso8601_utils.h:166
int_least32_t year
Definition: daw_json_parse_iso8601_utils.h:164
Definition: daw_json_parse_iso8601_utils.h:188
uint_least32_t hour
Definition: daw_json_parse_iso8601_utils.h:189
uint_least32_t second
Definition: daw_json_parse_iso8601_utils.h:191
uint_least32_t millisecond
Definition: daw_json_parse_iso8601_utils.h:192
uint_least32_t minute
Definition: daw_json_parse_iso8601_utils.h:190
Definition: daw_json_parse_iso8601_utils.h:272
std::int_least32_t year
Definition: daw_json_parse_iso8601_utils.h:273
std::uint_least32_t second
Definition: daw_json_parse_iso8601_utils.h:278
std::uint_least32_t month
Definition: daw_json_parse_iso8601_utils.h:274
std::uint_least32_t hour
Definition: daw_json_parse_iso8601_utils.h:276
std::uint_least32_t day
Definition: daw_json_parse_iso8601_utils.h:275
std::uint_least32_t minute
Definition: daw_json_parse_iso8601_utils.h:277
std::uint_least32_t millisecond
Definition: daw_json_parse_iso8601_utils.h:279
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:16