Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 42 additions & 30 deletions src/input/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,26 @@ pub fn pydate_as_date(py_date: &Bound<'_, PyAny>) -> PyResult<Date> {
})
}

impl<'py> IntoPyObject<'py> for EitherDate<'py> {
type Target = PyDate;
type Output = Bound<'py, PyDate>;
type Error = PyErr;

fn into_pyobject(self, py: Python<'py>) -> PyResult<Self::Output> {
impl<'py> EitherDate<'py> {
pub fn try_into_py(&self, py: Python<'py>, input: &(impl Input<'py> + ?Sized)) -> ValResult<PyObject> {
match self {
Self::Raw(date) => PyDate::new(py, date.year.into(), date.month, date.day),
Self::Py(date) => Ok(date),
Self::Raw(date) => {
if date.year == 0 {
return Err(ValError::new(
ErrorType::DateParsing {
error: Cow::Borrowed("year 0 is out of range"),
context: None,
},
input,
));
};
let py_date = PyDate::new(py, date.year.into(), date.month, date.day)?;
Ok(py_date.into())
}
Self::Py(py_date) => Ok(py_date.clone().into()),
}
}
}

impl EitherDate<'_> {
pub fn as_raw(&self) -> PyResult<Date> {
match self {
Self::Raw(date) => Ok(date.clone()),
Expand Down Expand Up @@ -278,30 +284,36 @@ pub fn pydatetime_as_datetime(py_dt: &Bound<'_, PyAny>) -> PyResult<DateTime> {
})
}

impl<'py> IntoPyObject<'py> for EitherDateTime<'py> {
type Target = PyDateTime;
type Output = Bound<'py, PyDateTime>;
type Error = PyErr;

fn into_pyobject(self, py: Python<'py>) -> PyResult<Self::Output> {
impl<'py> EitherDateTime<'py> {
pub fn try_into_py(&self, py: Python<'py>, input: &(impl Input<'py> + ?Sized)) -> ValResult<PyObject> {
match self {
Self::Raw(dt) => PyDateTime::new(
py,
dt.date.year.into(),
dt.date.month,
dt.date.day,
dt.time.hour,
dt.time.minute,
dt.time.second,
dt.time.microsecond,
time_as_tzinfo(py, &dt.time)?.as_ref(),
),
Self::Py(dt) => Ok(dt),
Self::Raw(dt) => {
if dt.date.year == 0 {
return Err(ValError::new(
ErrorType::DatetimeParsing {
error: Cow::Borrowed("year 0 is out of range"),
context: None,
},
input,
));
};
let py_dt = PyDateTime::new(
py,
dt.date.year.into(),
dt.date.month,
dt.date.day,
dt.time.hour,
dt.time.minute,
dt.time.second,
dt.time.microsecond,
time_as_tzinfo(py, &dt.time)?.as_ref(),
)?;
Ok(py_dt.into())
}
Self::Py(py_dt) => Ok(py_dt.clone().into()),
}
}
}

impl EitherDateTime<'_> {
pub fn as_raw(&self) -> PyResult<DateTime> {
match self {
Self::Raw(dt) => Ok(dt.clone()),
Expand Down
3 changes: 1 addition & 2 deletions src/validators/date.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use pyo3::intern;
use pyo3::prelude::*;
use pyo3::types::{PyDate, PyDict, PyString};
use pyo3::IntoPyObjectExt;
use speedate::{Date, Time};
use strum::EnumMessage;

Expand Down Expand Up @@ -98,7 +97,7 @@ impl Validator for DateValidator {
}
}
}
Ok(date.into_py_any(py)?)
date.try_into_py(py, input)
}

fn get_name(&self) -> &str {
Expand Down
3 changes: 1 addition & 2 deletions src/validators/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use pyo3::intern;
use pyo3::prelude::*;
use pyo3::sync::GILOnceCell;
use pyo3::types::{PyDict, PyString};
use pyo3::IntoPyObjectExt;
use speedate::{DateTime, Time};
use std::cmp::Ordering;
use strum::EnumMessage;
Expand Down Expand Up @@ -131,7 +130,7 @@ impl Validator for DateTimeValidator {
tz_constraint.tz_check(speedate_dt.time.tz_offset, input)?;
}
}
Ok(datetime.into_py_any(py)?)
datetime.try_into_py(py, input)
}

fn get_name(&self) -> &str {
Expand Down
6 changes: 6 additions & 0 deletions tests/validators/test_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@
),
pytest.param('-', Err('Input should be a valid date or datetime, input is too short'), id='minus'),
pytest.param('+', Err('Input should be a valid date or datetime, input is too short'), id='pus'),
pytest.param('0001-01-01', date(1, 1, 1), id='min-date'),
pytest.param(
'0000-12-31',
Err('Input should be a valid date in the format YYYY-MM-DD, year 0 is out of range [type=date_parsing,'),
id='year-0',
),
],
)
def test_date(input_value, expected):
Expand Down
8 changes: 8 additions & 0 deletions tests/validators/test_datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@
'Input should be a valid datetime or date, day value is outside expected range [type=datetime_from_date_parsing,'
),
),
(
'0001-01-01T00:00:00.000000Z',
datetime(1, 1, 1, tzinfo=timezone.utc),
),
(
'0000-12-31T23:59:59.999999Z',
Err('Input should be a valid datetime, year 0 is out of range [type=datetime_parsing,'),
),
],
)
def test_datetime(input_value, expected):
Expand Down
Loading