98 std::uint32_t dy, std::uint32_t hr,
99 std::uint32_t mn, std::uint32_t se,
101 using Clock =
typename TP::clock;
102 using Duration =
typename TP::duration;
103 constexpr auto calc =
104 []( std::int32_t y, std::uint32_t m, std::uint32_t d, std::uint32_t h,
105 std::uint32_t min, std::uint32_t s,
107 y -=
static_cast<std::int32_t
>( m ) <= 2;
108 std::int32_t
const era = ( y >= 0 ? y : y - 399 ) / 400;
109 auto const yoe =
static_cast<std::uint32_t
>(
110 static_cast<std::int32_t
>( y ) - era * 400 );
111 auto const doy =
static_cast<std::uint32_t
>(
112 ( 153 * (
static_cast<std::int32_t
>( m ) +
113 (
static_cast<std::int32_t
>( m ) > 2 ? -3 : 9 ) ) +
116 static_cast<std::int32_t
>( d ) - 1 );
117 std::uint32_t
const doe =
118 yoe * 365 + yoe / 4 - yoe / 100 + doy;
119 auto const days_since_epoch =
120 static_cast<int64_t
>( era ) * 146097LL +
121 static_cast<std::int64_t
>( doe ) - 719468LL;
123 using Days = std::chrono::duration<std::int32_t, std::ratio<86400>>;
125 std::chrono::floor<Duration>( std::chrono::nanoseconds( nano ) );
126 return std::chrono::time_point<std::chrono::system_clock,
128 ( Days( days_since_epoch ) + std::chrono::hours( h ) +
129 std::chrono::minutes( min ) +
130 std::chrono::seconds(
static_cast<std::uint32_t
>( s ) ) +
138 auto result = calc( yr, mo, dy, hr, mn, se, ns );
140 if constexpr( std::is_same_v<Clock, std::chrono::system_clock> ) {
143#if defined( __cpp_lib_chrono ) and __cpp_lib_chrono >= 201907
145 auto const match_duration =
146 std::chrono::time_point_cast<Duration>( result );
147 auto const match_clock =
148 std::chrono::clock_cast<Clock>( match_duration );
154 auto const system_epoch = std::chrono::floor<std::chrono::hours>(
155 std::chrono::system_clock::now( ).time_since_epoch( ) +
156 std::chrono::minutes( 30 ) );
157 auto const clock_epoch = std::chrono::floor<std::chrono::hours>(
158 Clock::now( ).time_since_epoch( ) + std::chrono::minutes( 30 ) );
160 constexpr auto offset =
161 std::chrono::duration_cast<std::chrono::milliseconds>(
162 clock_epoch - system_epoch );
163 return std::chrono::duration_cast<Duration>( result + offset );
177 result.day = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
178 std::data( timestamp_str.pop_back( 2U ) ) );
180 ErrorReason::InvalidTimestamp );
181 if( not parse_utils::is_number( timestamp_str.back( ) ) ) {
182 timestamp_str.remove_suffix( );
184 result.month = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
185 std::data( timestamp_str.pop_back( 2U ) ) );
187 ErrorReason::InvalidTimestamp );
188 if( not parse_utils::is_number( timestamp_str.back( ) ) ) {
189 timestamp_str.remove_suffix( );
192 datetime_details::parse_number<std::int_least32_t>( timestamp_str );
206 result.hour = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
207 std::data( timestamp_str.pop_front( 2 ) ) );
209 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
210 timestamp_str.remove_prefix( );
212 result.minute = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
213 std::data( timestamp_str.pop_front( 2 ) ) );
215 if( timestamp_str.empty( ) ) {
218 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
219 timestamp_str.remove_prefix( );
221 result.second = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
222 std::data( timestamp_str.pop_front( 2 ) ) );
224 if( timestamp_str.empty( ) ) {
227 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
228 timestamp_str.remove_prefix( );
230 auto const nanosecond_str = timestamp_str.substr(
231 0, std::min( timestamp_str.size( ), std::size_t{ 9 } ) );
233 datetime_details::parse_number<std::uint64_t>( nanosecond_str );
234 result.nanosecond *= daw::cxmath::pow10( 9 - timestamp_str.size( ) );
240 constexpr daw::string_view t_str =
"T";
241 auto const date_str = ts.pop_front_until( t_str );
244 ErrorReason::InvalidTimestamp );
251 return not( parse_utils::is_number( c ) | ( c ==
':' ) |
256 if( not( ts.empty( ) or ts.front( ) ==
'Z' ) ) {
258 ErrorReason::InvalidTimestamp );
262 switch( ts.front( ) ) {
272 auto hr_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
275 daw::json::ErrorReason::InvalidTimestamp );
276 if( ts.front( ) ==
':' ) {
279 auto mn_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
282 daw::json::ErrorReason::InvalidTimestamp );
286 hms.
hour -= hr_offset;
290 hms.
hour += hr_offset;
310 std::chrono::time_point<Clock, Duration>
const &tp ) {
311 auto dur_from_epoch = tp.time_since_epoch( );
313 std::chrono::duration<std::int_least32_t, std::ratio<86400>>;
314 auto const days_since_epoch =
315 std::chrono::duration_cast<Days>( dur_from_epoch );
316 std::int_least32_t z = days_since_epoch.count( );
318 std::int_least32_t
const era = ( z >= 0 ? z : z - 146096 ) / 146097;
320 static_cast<std::uint_least32_t
>( z - era * 146097 );
321 std::uint_least32_t
const yoe =
322 ( doe - doe / 1460 + doe / 36524 - doe / 146096 ) / 365;
323 std::int_least32_t
const y =
324 static_cast<std::int_least32_t
>( yoe ) + era * 400;
325 std::uint_least32_t
const doy =
326 doe - ( 365 * yoe + yoe / 4 - yoe / 100 );
327 std::uint_least32_t
const mp = ( 5 * doy + 2 ) / 153;
328 std::uint_least32_t
const d = doy - ( 153 * mp + 2 ) / 5 + 1;
329 auto const m =
static_cast<std::uint_least32_t
>(
330 static_cast<std::int_least32_t
>( mp ) +
331 (
static_cast<std::int_least32_t
>( mp ) < 10 ? 3 : -9 ) );
333 dur_from_epoch -= days_since_epoch;
335 std::chrono::duration_cast<std::chrono::hours>( dur_from_epoch );
336 dur_from_epoch -= hrs;
338 std::chrono::duration_cast<std::chrono::minutes>( dur_from_epoch );
339 dur_from_epoch -= min;
341 std::chrono::duration_cast<std::chrono::seconds>( dur_from_epoch );
342 dur_from_epoch -= sec;
343 auto const dur = std::chrono::duration_cast<std::chrono::nanoseconds>(
345 return ymdhms{ y + ( m <= 2 ),
348 static_cast<std::uint_least32_t
>( hrs.count( ) ),
349 static_cast<std::uint_least32_t
>( min.count( ) ),
350 static_cast<std::uint_least32_t
>( sec.count( ) ),
351 static_cast<std::uint64_t
>( dur.count( ) ) };
390 std::chrono::time_point<std::chrono::system_clock, Duration> tp ) {
391 using days = std::chrono::duration<long, std::ratio<86400>>;
393 std::chrono::duration_cast<days>( tp.time_since_epoch( ) ).count( );
394 auto const dow = z >= -4L ? ( z + 4L ) % 7L : ( z + 5L ) % 7L + 6L;
432 switch( datetime_details::month2num( ts ) ) {
433 case datetime_details::month2num(
"Jan" ):
435 case datetime_details::month2num(
"Feb" ):
437 case datetime_details::month2num(
"Mar" ):
439 case datetime_details::month2num(
"Apr" ):
441 case datetime_details::month2num(
"May" ):
443 case datetime_details::month2num(
"Jun" ):
445 case datetime_details::month2num(
"Jul" ):
447 case datetime_details::month2num(
"Aug" ):
449 case datetime_details::month2num(
"Sep" ):
451 case datetime_details::month2num(
"Oct" ):
453 case datetime_details::month2num(
"Nov" ):
455 case datetime_details::month2num(
"Dec" ):