diff --git a/src/input/datetime.rs b/src/input/datetime.rs index c339f3cbf..a91713872 100644 --- a/src/input/datetime.rs +++ b/src/input/datetime.rs @@ -228,18 +228,9 @@ pub fn int_as_datetime(input: &dyn Input, timestamp: i64, timestamp_microseconds pub fn float_as_datetime(input: &dyn Input, timestamp: f64) -> ValResult { let microseconds = timestamp.fract().abs() * 1_000_000.0; - // WARNING: 0.1 is plucked virtually from thin air to make it work - // since an input of timestamp=1655205632.331557, gives microseconds=331557.035446167 - // it maybe need to be adjusted, up OR down - if microseconds % 1.0 > 0.1 { - return err_val_error!( - input_value = InputValue::InputRef(input), - kind = ErrorKind::DateTimeParsing, - // message copied from speedate - context = context!("parsing_error" => "second fraction must contain 6 digits of fewer") - ); - } - int_as_datetime(input, timestamp.floor() as i64, microseconds as u32) + // checking for extra digits in microseconds is unreliable with large floats, + // so we just round to the nearest microsecond + int_as_datetime(input, timestamp.floor() as i64, microseconds.round() as u32) } pub fn date_as_datetime(date: &PyDate) -> PyResult { @@ -288,16 +279,8 @@ pub fn int_as_time(input: &dyn Input, timestamp: i64, timestamp_microseconds: u3 pub fn float_as_time(input: &dyn Input, timestamp: f64) -> ValResult { let microseconds = timestamp.fract().abs() * 1_000_000.0; - // WARNING: as above - if microseconds % 1.0 > 0.1 { - return err_val_error!( - input_value = InputValue::InputRef(input), - kind = ErrorKind::TimeParsing, - // message copied from speedate - context = context!("parsing_error" => "second fraction must contain 6 digits of fewer") - ); - } - int_as_time(input, timestamp.floor() as i64, microseconds as u32) + // round for same reason as above + int_as_time(input, timestamp.floor() as i64, microseconds.round() as u32) } #[pyclass(module = "pydantic_core._pydantic_core", extends = PyTzInfo)] diff --git a/tests/validators/test_datetime.py b/tests/validators/test_datetime.py index 577d0dc96..1028e7e4d 100644 --- a/tests/validators/test_datetime.py +++ b/tests/validators/test_datetime.py @@ -22,6 +22,9 @@ ((1,), Err('Value must be a valid datetime [kind=datetime_type')), (time(1, 2, 3), Err('Value must be a valid datetime [kind=datetime_type')), (Decimal('1654646400'), datetime(2022, 6, 8)), + (Decimal('1654646400.123456'), datetime(2022, 6, 8, 0, 0, 0, 123456)), + (Decimal('1654646400.1234564'), datetime(2022, 6, 8, 0, 0, 0, 123456)), + (Decimal('1654646400.1234568'), datetime(2022, 6, 8, 0, 0, 0, 123457)), (253_402_300_800_000, Err('must be a valid datetime, dates after 9999 are not supported as unix timestamps')), (-20_000_000_000, Err('must be a valid datetime, dates before 1600 are not supported as unix timestamps')), ], diff --git a/tests/validators/test_time.py b/tests/validators/test_time.py index ac2061096..aa18d3044 100644 --- a/tests/validators/test_time.py +++ b/tests/validators/test_time.py @@ -22,11 +22,8 @@ pytest.param(123, time(0, 2, 3), id='int'), pytest.param(Decimal('123'), time(0, 2, 3), id='decimal'), pytest.param(Decimal('123.123456'), time(0, 2, 3, 123456), id='decimal-6dig'), - pytest.param( - Decimal('123.1234567'), - Err('Value must be in a valid time format, second fraction must contain 6 digits of fewer'), - id='decimal-6dig', - ), + pytest.param(Decimal('123.1234562'), time(0, 2, 3, 123456), id='decimal-7dig-up'), + pytest.param(Decimal('123.1234568'), time(0, 2, 3, 123457), id='decimal-7dig-down'), ], ) def test_time(input_value, expected): @@ -127,6 +124,8 @@ def test_time_strict_json(input_value, expected): ({'le': time(1)}, '00:12', time(0, 12)), ({'le': time(1)}, '01:00', time(1, 0)), ({'le': time(1)}, '01:01', Err('Value must be less than or equal to 01:00:00')), + ({'le': time(1)}, time(1), time(1, 0)), + ({'le': time(1)}, time(1, 1), Err('Value must be less than or equal to 01:00:00')), ({'lt': time(1)}, '00:59', time(0, 59)), ({'lt': time(1)}, '01:00', Err('Value must be less than 01:00:00')), ({'ge': time(1)}, '01:00', time(1)),