@@ -6,6 +6,7 @@ use pyo3::pyclass::CompareOp;
66use pyo3:: types:: PyTuple ;
77use pyo3:: types:: { PyDate , PyDateTime , PyDelta , PyDeltaAccess , PyDict , PyTime , PyTzInfo } ;
88use pyo3:: IntoPyObjectExt ;
9+ use speedate:: DateConfig ;
910use speedate:: {
1011 Date , DateTime , DateTimeConfig , Duration , MicrosecondsPrecisionOverflowBehavior , ParseError , Time , TimeConfig ,
1112} ;
@@ -21,6 +22,7 @@ use super::Input;
2122use crate :: errors:: ToErrorValue ;
2223use crate :: errors:: { ErrorType , ValError , ValResult } ;
2324use crate :: tools:: py_err;
25+ use crate :: validators:: TemporalUnitMode ;
2426
2527#[ cfg_attr( debug_assertions, derive( Debug ) ) ]
2628pub enum EitherDate < ' py > {
@@ -411,8 +413,12 @@ impl<'py> EitherDateTime<'py> {
411413 }
412414}
413415
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 ( ) ) {
416422 Ok ( date) => Ok ( date. into ( ) ) ,
417423 Err ( err) => Err ( ValError :: new (
418424 ErrorType :: DateParsing {
@@ -451,6 +457,7 @@ pub fn bytes_as_datetime<'py>(
451457 input : & ( impl Input < ' py > + ?Sized ) ,
452458 bytes : & [ u8 ] ,
453459 microseconds_overflow_behavior : MicrosecondsPrecisionOverflowBehavior ,
460+ mode : TemporalUnitMode ,
454461) -> ValResult < EitherDateTime < ' py > > {
455462 match DateTime :: parse_bytes_with_config (
456463 bytes,
@@ -459,7 +466,7 @@ pub fn bytes_as_datetime<'py>(
459466 microseconds_precision_overflow_behavior : microseconds_overflow_behavior,
460467 unix_timestamp_offset : Some ( 0 ) ,
461468 } ,
462- .. Default :: default ( )
469+ timestamp_unit : mode . into ( ) ,
463470 } ,
464471 ) {
465472 Ok ( dt) => Ok ( dt. into ( ) ) ,
@@ -477,6 +484,7 @@ pub fn int_as_datetime<'py>(
477484 input : & ( impl Input < ' py > + ?Sized ) ,
478485 timestamp : i64 ,
479486 timestamp_microseconds : u32 ,
487+ mode : TemporalUnitMode ,
480488) -> ValResult < EitherDateTime < ' py > > {
481489 match DateTime :: from_timestamp_with_config (
482490 timestamp,
@@ -486,7 +494,7 @@ pub fn int_as_datetime<'py>(
486494 unix_timestamp_offset : Some ( 0 ) ,
487495 ..Default :: default ( )
488496 } ,
489- .. Default :: default ( )
497+ timestamp_unit : mode . into ( ) ,
490498 } ,
491499 ) {
492500 Ok ( dt) => Ok ( dt. into ( ) ) ,
@@ -514,12 +522,31 @@ macro_rules! nan_check {
514522 } ;
515523}
516524
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 > > {
518530 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+ }
523550}
524551
525552pub fn date_as_datetime < ' py > ( date : & Bound < ' py , PyDate > ) -> PyResult < EitherDateTime < ' py > > {
0 commit comments