@@ -6,6 +6,7 @@ use pyo3::pyclass::CompareOp;
6
6
use pyo3:: types:: PyTuple ;
7
7
use pyo3:: types:: { PyDate , PyDateTime , PyDelta , PyDeltaAccess , PyDict , PyTime , PyTzInfo } ;
8
8
use pyo3:: IntoPyObjectExt ;
9
+ use speedate:: DateConfig ;
9
10
use speedate:: {
10
11
Date , DateTime , DateTimeConfig , Duration , MicrosecondsPrecisionOverflowBehavior , ParseError , Time , TimeConfig ,
11
12
} ;
@@ -21,6 +22,7 @@ use super::Input;
21
22
use crate :: errors:: ToErrorValue ;
22
23
use crate :: errors:: { ErrorType , ValError , ValResult } ;
23
24
use crate :: tools:: py_err;
25
+ use crate :: validators:: TemporalUnitMode ;
24
26
25
27
#[ cfg_attr( debug_assertions, derive( Debug ) ) ]
26
28
pub enum EitherDate < ' py > {
@@ -411,8 +413,12 @@ impl<'py> EitherDateTime<'py> {
411
413
}
412
414
}
413
415
414
- pub fn bytes_as_date < ' py > ( input : & ( impl Input < ' py > + ?Sized ) , bytes : & [ u8 ] ) -> ValResult < EitherDate < ' py > > {
415
- match Date :: parse_bytes ( bytes) {
416
+ pub fn bytes_as_date < ' py > (
417
+ input : & ( impl Input < ' py > + ?Sized ) ,
418
+ bytes : & [ u8 ] ,
419
+ mode : TemporalUnitMode ,
420
+ ) -> ValResult < EitherDate < ' py > > {
421
+ match Date :: parse_bytes_with_config ( bytes, & DateConfig :: builder ( ) . timestamp_unit ( mode. into ( ) ) . build ( ) ) {
416
422
Ok ( date) => Ok ( date. into ( ) ) ,
417
423
Err ( err) => Err ( ValError :: new (
418
424
ErrorType :: DateParsing {
@@ -451,6 +457,7 @@ pub fn bytes_as_datetime<'py>(
451
457
input : & ( impl Input < ' py > + ?Sized ) ,
452
458
bytes : & [ u8 ] ,
453
459
microseconds_overflow_behavior : MicrosecondsPrecisionOverflowBehavior ,
460
+ mode : TemporalUnitMode ,
454
461
) -> ValResult < EitherDateTime < ' py > > {
455
462
match DateTime :: parse_bytes_with_config (
456
463
bytes,
@@ -459,7 +466,7 @@ pub fn bytes_as_datetime<'py>(
459
466
microseconds_precision_overflow_behavior : microseconds_overflow_behavior,
460
467
unix_timestamp_offset : Some ( 0 ) ,
461
468
} ,
462
- .. Default :: default ( )
469
+ timestamp_unit : mode . into ( ) ,
463
470
} ,
464
471
) {
465
472
Ok ( dt) => Ok ( dt. into ( ) ) ,
@@ -477,6 +484,7 @@ pub fn int_as_datetime<'py>(
477
484
input : & ( impl Input < ' py > + ?Sized ) ,
478
485
timestamp : i64 ,
479
486
timestamp_microseconds : u32 ,
487
+ mode : TemporalUnitMode ,
480
488
) -> ValResult < EitherDateTime < ' py > > {
481
489
match DateTime :: from_timestamp_with_config (
482
490
timestamp,
@@ -486,7 +494,7 @@ pub fn int_as_datetime<'py>(
486
494
unix_timestamp_offset : Some ( 0 ) ,
487
495
..Default :: default ( )
488
496
} ,
489
- .. Default :: default ( )
497
+ timestamp_unit : mode . into ( ) ,
490
498
} ,
491
499
) {
492
500
Ok ( dt) => Ok ( dt. into ( ) ) ,
@@ -514,12 +522,31 @@ macro_rules! nan_check {
514
522
} ;
515
523
}
516
524
517
- pub fn float_as_datetime < ' py > ( input : & ( impl Input < ' py > + ?Sized ) , timestamp : f64 ) -> ValResult < EitherDateTime < ' py > > {
525
+ pub fn float_as_datetime < ' py > (
526
+ input : & ( impl Input < ' py > + ?Sized ) ,
527
+ timestamp : f64 ,
528
+ mode : TemporalUnitMode ,
529
+ ) -> ValResult < EitherDateTime < ' py > > {
518
530
nan_check ! ( input, timestamp, DatetimeParsing ) ;
519
- let microseconds = timestamp. fract ( ) . abs ( ) * 1_000_000.0 ;
520
- // checking for extra digits in microseconds is unreliable with large floats,
521
- // so we just round to the nearest microsecond
522
- int_as_datetime ( input, timestamp. floor ( ) as i64 , microseconds. round ( ) as u32 )
531
+ match DateTime :: from_float_with_config (
532
+ timestamp,
533
+ & DateTimeConfig {
534
+ time_config : TimeConfig {
535
+ unix_timestamp_offset : Some ( 0 ) ,
536
+ ..Default :: default ( )
537
+ } ,
538
+ timestamp_unit : mode. into ( ) ,
539
+ } ,
540
+ ) {
541
+ Ok ( dt) => Ok ( dt. into ( ) ) ,
542
+ Err ( err) => Err ( ValError :: new (
543
+ ErrorType :: DatetimeParsing {
544
+ error : Cow :: Borrowed ( err. get_documentation ( ) . unwrap_or_default ( ) ) ,
545
+ context : None ,
546
+ } ,
547
+ input,
548
+ ) ) ,
549
+ }
523
550
}
524
551
525
552
pub fn date_as_datetime < ' py > ( date : & Bound < ' py , PyDate > ) -> PyResult < EitherDateTime < ' py > > {
0 commit comments