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 DAW_CPP23_STATIC_LOCAL
constexpr auto calc =
111 y -=
static_cast<std::int32_t
>( m ) <= 2;
112 std::int32_t
const era = ( y >= 0 ? y : y - 399 ) / 400;
113 auto const yoe =
static_cast<std::uint32_t
>(
114 static_cast<std::int32_t
>( y ) - era * 400 );
115 auto const doy =
static_cast<std::uint32_t
>(
116 ( 153 * (
static_cast<std::int32_t
>( m ) +
117 (
static_cast<std::int32_t
>( m ) > 2 ? -3 : 9 ) ) +
120 static_cast<std::int32_t
>( d ) - 1 );
121 std::uint32_t
const doe =
122 yoe * 365 + yoe / 4 - yoe / 100 + doy;
123 auto const days_since_epoch =
124 static_cast<int64_t
>( era ) * 146097LL +
125 static_cast<std::int64_t
>( doe ) - 719468LL;
127 using Days = std::chrono::duration<std::int32_t, std::ratio<86400>>;
129 std::chrono::floor<Duration>( std::chrono::nanoseconds( nano ) );
130 return std::chrono::time_point<std::chrono::system_clock,
132 ( Days( days_since_epoch ) + std::chrono::hours( h ) +
133 std::chrono::minutes( min ) +
134 std::chrono::seconds(
static_cast<std::uint32_t
>( s ) ) +
142 auto result = calc( yr, mo, dy, hr, mn, se, ns );
144 if constexpr( std::is_same_v<Clock, std::chrono::system_clock> ) {
147#if defined( __cpp_lib_chrono ) and __cpp_lib_chrono >= 201907
149 auto const match_duration =
150 std::chrono::time_point_cast<Duration>( result );
151 auto const match_clock =
152 std::chrono::clock_cast<Clock>( match_duration );
158 auto const system_epoch = std::chrono::floor<std::chrono::hours>(
159 std::chrono::system_clock::now( ).time_since_epoch( ) +
160 std::chrono::minutes( 30 ) );
161 auto const clock_epoch = std::chrono::floor<std::chrono::hours>(
162 Clock::now( ).time_since_epoch( ) + std::chrono::minutes( 30 ) );
164 DAW_CPP23_STATIC_LOCAL
constexpr auto offset =
165 std::chrono::duration_cast<std::chrono::milliseconds>(
166 clock_epoch - system_epoch );
167 return std::chrono::duration_cast<Duration>( result + offset );
181 result.
day = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
182 std::data( timestamp_str.pop_back( 2U ) ) );
184 ErrorReason::InvalidTimestamp );
185 if( not parse_utils::is_number( timestamp_str.back( ) ) ) {
186 timestamp_str.remove_suffix( );
188 result.month = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
189 std::data( timestamp_str.pop_back( 2U ) ) );
191 ErrorReason::InvalidTimestamp );
192 if( not parse_utils::is_number( timestamp_str.back( ) ) ) {
193 timestamp_str.remove_suffix( );
196 datetime_details::parse_number<std::int_least32_t>( timestamp_str );
210 result.
hour = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
211 std::data( timestamp_str.pop_front( 2 ) ) );
213 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
214 timestamp_str.remove_prefix( );
216 result.minute = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
217 std::data( timestamp_str.pop_front( 2 ) ) );
219 if( timestamp_str.empty( ) ) {
222 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
223 timestamp_str.remove_prefix( );
225 result.second = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
226 std::data( timestamp_str.pop_front( 2 ) ) );
228 if( timestamp_str.empty( ) ) {
231 if( not parse_utils::is_number( timestamp_str.front( ) ) ) {
232 timestamp_str.remove_prefix( );
234 auto const nanosecond_str = timestamp_str.substr(
235 0, std::min( timestamp_str.size( ), std::size_t{ 9 } ) );
237 datetime_details::parse_number<std::uint64_t>( nanosecond_str );
238 result.nanosecond *= daw::cxmath::pow10( 9 - timestamp_str.size( ) );
244 DAW_CPP23_STATIC_LOCAL
constexpr daw::string_view t_str =
"T";
245 auto const date_str = ts.pop_front_until( t_str );
249 ErrorReason::InvalidTimestamp );
256 return not( parse_utils::is_number( c ) | ( c ==
':' ) |
261 if( not( ts.empty( ) or ts.front( ) ==
'Z' ) ) {
263 ErrorReason::InvalidTimestamp );
267 switch( ts.front( ) ) {
277 auto hr_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
280 daw::json::ErrorReason::InvalidTimestamp );
281 if( ts.front( ) ==
':' ) {
284 auto mn_offset = parse_utils::parse_unsigned<std::uint_least32_t, 2>(
287 daw::json::ErrorReason::InvalidTimestamp );
291 hms.hour -= hr_offset;
292 hms.minute -= mn_offset;
295 hms.hour += hr_offset;
296 hms.minute += mn_offset;
299 return civil_to_time_point<TP>( ymd.
year,
320 auto dur_from_epoch = tp.time_since_epoch( );
322 std::chrono::duration<std::int_least32_t, std::ratio<86400>>;
323 auto const days_since_epoch =
324 std::chrono::duration_cast<Days>( dur_from_epoch );
325 std::int_least32_t z = days_since_epoch.count( );
327 std::int_least32_t
const era = ( z >= 0 ? z : z - 146096 ) / 146097;
329 static_cast<std::uint_least32_t
>( z - era * 146097 );
330 std::uint_least32_t
const yoe =
331 ( doe - doe / 1460 + doe / 36524 - doe / 146096 ) / 365;
332 std::int_least32_t
const y =
333 static_cast<std::int_least32_t
>( yoe ) + era * 400;
334 std::uint_least32_t
const doy =
335 doe - ( 365 * yoe + yoe / 4 - yoe / 100 );
336 std::uint_least32_t
const mp = ( 5 * doy + 2 ) / 153;
337 std::uint_least32_t
const d = doy - ( 153 * mp + 2 ) / 5 + 1;
338 auto const m =
static_cast<std::uint_least32_t
>(
339 static_cast<std::int_least32_t
>( mp ) +
340 (
static_cast<std::int_least32_t
>( mp ) < 10 ? 3 : -9 ) );
342 dur_from_epoch -= days_since_epoch;
344 std::chrono::duration_cast<std::chrono::hours>( dur_from_epoch );
345 dur_from_epoch -= hrs;
347 std::chrono::duration_cast<std::chrono::minutes>( dur_from_epoch );
348 dur_from_epoch -= min;
350 std::chrono::duration_cast<std::chrono::seconds>( dur_from_epoch );
351 dur_from_epoch -= sec;
352 auto const dur = std::chrono::duration_cast<std::chrono::nanoseconds>(
354 return ymdhms{ y + ( m <= 2 ),
357 static_cast<std::uint_least32_t
>( hrs.count( ) ),
358 static_cast<std::uint_least32_t
>( min.count( ) ),
359 static_cast<std::uint_least32_t
>( sec.count( ) ),
360 static_cast<std::uint64_t
>( dur.count( ) ) };
400 std::chrono::time_point<std::chrono::system_clock, Duration> tp ) {
401 using days = std::chrono::duration<long, std::ratio<86400>>;
403 std::chrono::duration_cast<days>( tp.time_since_epoch( ) ).count( );
404 auto const dow = z >= -4L ? ( z + 4L ) % 7L : ( z + 5L ) % 7L + 6L;
423 ErrorReason::InvalidTimestamp );
443 switch( datetime_details::month2num( ts ) ) {
444 case datetime_details::month2num(
"Jan" ):
446 case datetime_details::month2num(
"Feb" ):
448 case datetime_details::month2num(
"Mar" ):
450 case datetime_details::month2num(
"Apr" ):
452 case datetime_details::month2num(
"May" ):
454 case datetime_details::month2num(
"Jun" ):
456 case datetime_details::month2num(
"Jul" ):
458 case datetime_details::month2num(
"Aug" ):
460 case datetime_details::month2num(
"Sep" ):
462 case datetime_details::month2num(
"Oct" ):
464 case datetime_details::month2num(
"Nov" ):
466 case datetime_details::month2num(
"Dec" ):
471 ErrorReason::InvalidTimestamp );