100 std::uint32_t dy, std::uint32_t hr,
101 std::uint32_t mn, std::uint32_t se,
102 std::uint64_t attosecond ) {
103 using Clock =
typename TP::clock;
104 using Duration =
typename TP::duration;
105 DAW_CPP23_STATIC_LOCAL
constexpr auto calc =
113 y -=
static_cast<std::int32_t
>( m ) <= 2;
114 std::int32_t
const era = ( y >= 0 ? y : y - 399 ) / 400;
115 auto const yoe =
static_cast<std::uint32_t
>(
116 static_cast<std::int32_t
>( y ) - era * 400 );
117 auto const doy =
static_cast<std::uint32_t
>(
118 ( 153 * (
static_cast<std::int32_t
>( m ) +
119 (
static_cast<std::int32_t
>( m ) > 2 ? -3 : 9 ) ) +
122 static_cast<std::int32_t
>( d ) - 1 );
123 std::uint32_t
const doe =
124 yoe * 365 + yoe / 4 - yoe / 100 + doy;
125 auto const days_since_epoch =
126 static_cast<int64_t
>( era ) * 146097LL +
127 static_cast<std::int64_t
>( doe ) - 719468LL;
129 auto const dur = std::chrono::floor<Duration>(
130 attoseconds(
static_cast<std::int64_t
>( atto ) ) );
131 auto const whole_seconds =
132 std::chrono::seconds( days_since_epoch * 86400LL +
133 static_cast<std::int64_t
>( h ) * 3600LL +
134 static_cast<std::int64_t
>( min ) * 60LL +
135 static_cast<std::int64_t
>( s ) );
136 return std::chrono::time_point<std::chrono::system_clock,
138 ( std::chrono::duration_cast<Duration>( whole_seconds ) +
146 auto result = calc( yr, mo, dy, hr, mn, se, attosecond );
148 if constexpr( std::is_same_v<Clock, std::chrono::system_clock> ) {
151#if defined( __cpp_lib_chrono ) and __cpp_lib_chrono >= 201907
153 auto const match_duration =
154 std::chrono::time_point_cast<Duration>( result );
155 auto const match_clock =
156 std::chrono::clock_cast<Clock>( match_duration );
162 auto const system_epoch = std::chrono::floor<std::chrono::hours>(
163 std::chrono::system_clock::now( ).time_since_epoch( ) +
164 std::chrono::minutes( 30 ) );
165 auto const clock_epoch = std::chrono::floor<std::chrono::hours>(
166 Clock::now( ).time_since_epoch( ) + std::chrono::minutes( 30 ) );
168 DAW_CPP23_STATIC_LOCAL
constexpr auto offset =
169 std::chrono::duration_cast<std::chrono::milliseconds>(
170 clock_epoch - system_epoch );
171 return std::chrono::duration_cast<Duration>( result + offset );
185 result.
day = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
186 std::data( timestamp_str.pop_back( 2U ) ) );
188 ErrorReason::InvalidTimestamp );
189 if( not parse_utils::is_number( timestamp_str.back( ) ) ) {
190 timestamp_str.remove_suffix( );
192 result.month = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
193 std::data( timestamp_str.pop_back( 2U ) ) );
195 ErrorReason::InvalidTimestamp );
196 if( not parse_utils::is_number( timestamp_str.back( ) ) ) {
197 timestamp_str.remove_suffix( );
200 datetime_details::parse_number<std::int_least32_t>( timestamp_str );
214 result.
hour = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
215 std::data( timestamp_str.pop_front( 2 ) ) );
217 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
218 timestamp_str.remove_prefix( );
220 result.minute = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
221 std::data( timestamp_str.pop_front( 2 ) ) );
223 if( timestamp_str.empty( ) ) {
226 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
227 timestamp_str.remove_prefix( );
229 result.second = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
230 std::data( timestamp_str.pop_front( 2 ) ) );
232 if( timestamp_str.empty( ) ) {
236 ErrorReason::InvalidTimestamp );
237 timestamp_str.remove_prefix( );
239 ErrorReason::InvalidTimestamp );
240 for(
char const c : timestamp_str ) {
242 ErrorReason::InvalidTimestamp );
244 auto const precision =
245 std::min( timestamp_str.size( ), std::size_t{ 18 } );
246 auto const attosecond_str = timestamp_str.substr( 0, precision );
248 datetime_details::parse_number<std::uint64_t>( attosecond_str );
249 result.attosecond *= daw::cxmath::pow10( 18 - precision );
255 DAW_CPP23_STATIC_LOCAL
constexpr daw::string_view t_str =
"T";
256 auto const date_str = ts.pop_front_until( t_str );
260 ErrorReason::InvalidTimestamp );
267 return not( parse_utils::is_number( c ) | ( c ==
':' ) |
272 if( not( ts.empty( ) or ts.front( ) ==
'Z' ) ) {
274 ErrorReason::InvalidTimestamp );
278 switch( ts.front( ) ) {
288 auto hr_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
291 daw::json::ErrorReason::InvalidTimestamp );
292 if( ts.front( ) ==
':' ) {
295 auto mn_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
298 daw::json::ErrorReason::InvalidTimestamp );
302 hms.hour -= hr_offset;
303 hms.minute -= mn_offset;
306 hms.hour += hr_offset;
307 hms.minute += mn_offset;
310 return civil_to_time_point<TP>( ymd.
year,
331 auto dur_from_epoch = tp.time_since_epoch( );
333 std::chrono::duration<std::int_least32_t, std::ratio<86400>>;
334 auto const whole_seconds =
335 std::chrono::floor<std::chrono::seconds>( dur_from_epoch );
336 auto const days_since_epoch = std::chrono::floor<Days>( whole_seconds );
337 std::int_least32_t z = days_since_epoch.count( );
339 std::int_least32_t
const era = ( z >= 0 ? z : z - 146096 ) / 146097;
341 static_cast<std::uint_least32_t
>( z - era * 146097 );
342 std::uint_least32_t
const yoe =
343 ( doe - doe / 1460 + doe / 36524 - doe / 146096 ) / 365;
344 std::int_least32_t
const y =
345 static_cast<std::int_least32_t
>( yoe ) + era * 400;
346 std::uint_least32_t
const doy =
347 doe - ( 365 * yoe + yoe / 4 - yoe / 100 );
348 std::uint_least32_t
const mp = ( 5 * doy + 2 ) / 153;
349 std::uint_least32_t
const d = doy - ( 153 * mp + 2 ) / 5 + 1;
350 auto const m =
static_cast<std::uint_least32_t
>(
351 static_cast<std::int_least32_t
>( mp ) +
352 (
static_cast<std::int_least32_t
>( mp ) < 10 ? 3 : -9 ) );
356 std::chrono::duration_cast<std::chrono::seconds>( days_since_epoch );
358 std::chrono::duration_cast<std::chrono::hours>( dur_in_day );
361 std::chrono::duration_cast<std::chrono::minutes>( dur_in_day );
364 std::chrono::duration_cast<std::chrono::seconds>( dur_in_day );
365 auto const subseconds =
367 std::chrono::duration_cast<Duration>( whole_seconds );
368 auto const dur = std::chrono::duration_cast<attoseconds>( subseconds );
369 return ymdhms{ y + ( m <= 2 ),
372 static_cast<std::uint_least32_t
>( hrs.count( ) ),
373 static_cast<std::uint_least32_t
>( min.count( ) ),
374 static_cast<std::uint_least32_t
>( sec.count( ) ),
375 static_cast<std::uint64_t
>( dur.count( ) ) };
415 std::chrono::time_point<std::chrono::system_clock, Duration> tp ) {
416 using days = std::chrono::duration<long, std::ratio<86400>>;
418 std::chrono::duration_cast<days>( tp.time_since_epoch( ) ).count( );
419 auto const dow = z >= -4L ? ( z + 4L ) % 7L : ( z + 5L ) % 7L + 6L;
438 ErrorReason::InvalidTimestamp );
458 switch( datetime_details::month2num( ts ) ) {
459 case datetime_details::month2num(
"Jan" ):
461 case datetime_details::month2num(
"Feb" ):
463 case datetime_details::month2num(
"Mar" ):
465 case datetime_details::month2num(
"Apr" ):
467 case datetime_details::month2num(
"May" ):
469 case datetime_details::month2num(
"Jun" ):
471 case datetime_details::month2num(
"Jul" ):
473 case datetime_details::month2num(
"Aug" ):
475 case datetime_details::month2num(
"Sep" ):
477 case datetime_details::month2num(
"Oct" ):
479 case datetime_details::month2num(
"Nov" ):
481 case datetime_details::month2num(
"Dec" ):
486 ErrorReason::InvalidTimestamp );