Change datetime constructors to use Rust Option

This makes it cleaner to call PyTime::new and PyDateTime::new from Rust
without needing to retrieve a Python None.
This commit is contained in:
Paul Ganssle 2018-08-20 13:52:19 -04:00
parent 09ee50d4ca
commit bcc27bd522
No known key found for this signature in database
GPG Key ID: CD54FCE3D964BEFB
3 changed files with 56 additions and 24 deletions

View File

@ -102,7 +102,7 @@ impl PyDateTime {
minute: u32,
second: u32,
microsecond: u32,
tzinfo: &PyObject,
tzinfo: Option<&PyObject>,
) -> PyResult<Py<PyDateTime>> {
unsafe {
let ptr = PyDateTimeAPI.DateTime_FromDateAndTime.unwrap()(
@ -113,7 +113,10 @@ impl PyDateTime {
minute as c_int,
second as c_int,
microsecond as c_int,
tzinfo.as_ptr(),
match tzinfo {
Some(o) => o.as_ptr(),
None => py.None().as_ptr(),
},
PyDateTimeAPI.DateTimeType,
);
Py::from_owned_ptr_or_err(py, ptr)
@ -184,7 +187,7 @@ impl PyTime {
minute: u32,
second: u32,
microsecond: u32,
tzinfo: &PyObject,
tzinfo: Option<&PyObject>,
) -> PyResult<Py<PyTime>> {
unsafe {
let ptr = PyDateTimeAPI.Time_FromTime.unwrap()(
@ -192,7 +195,10 @@ impl PyTime {
minute as c_int,
second as c_int,
microsecond as c_int,
tzinfo.as_ptr(),
match tzinfo {
Some(o) => o.as_ptr(),
None => py.None().as_ptr(),
},
PyDateTimeAPI.TimeType,
);
Py::from_owned_ptr_or_err(py, ptr)
@ -206,7 +212,7 @@ impl PyTime {
minute: u32,
second: u32,
microsecond: u32,
tzinfo: &PyObject,
tzinfo: Option<&PyObject>,
fold: bool,
) -> PyResult<Py<PyTime>> {
unsafe {
@ -215,7 +221,10 @@ impl PyTime {
minute as c_int,
second as c_int,
microsecond as c_int,
tzinfo.as_ptr(),
match tzinfo {
Some(o) => o.as_ptr(),
None => py.None().as_ptr(),
},
fold as c_int,
PyDateTimeAPI.TimeType,
);

View File

@ -13,15 +13,6 @@ use pyo3::prelude::{PyDict, PyTuple};
use pyo3::{ObjectProtocol, ToPyObject};
use pyo3::{Py, PyResult, Python};
macro_rules! to_pyobject {
($py:expr, $o:ident) => {
match $o {
Some(t) => t.to_object($py),
None => $py.None(),
}
};
}
#[pyfunction]
fn make_date(py: Python, year: u32, month: u32, day: u32) -> PyResult<Py<PyDate>> {
PyDate::new(py, year, month, day)
@ -48,8 +39,14 @@ fn make_time(
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
) -> PyResult<Py<PyTime>> {
let tzi: PyObject = to_pyobject!(py, tzinfo);
PyTime::new(py, hour, minute, second, microsecond, &tzi)
PyTime::new(
py,
hour,
minute,
second,
microsecond,
tzinfo.map(|o| o.to_object(py)).as_ref(),
)
}
#[cfg(Py_3_6)]
@ -63,8 +60,15 @@ fn time_with_fold(
tzinfo: Option<&PyTzInfo>,
fold: bool,
) -> PyResult<Py<PyTime>> {
let tzi = to_pyobject!(py, tzinfo);
PyTime::new_with_fold(py, hour, minute, second, microsecond, &tzi, fold)
PyTime::new_with_fold(
py,
hour,
minute,
second,
microsecond,
tzinfo.map(|o| o.to_object(py)).as_ref(),
fold,
)
}
#[pyfunction]
@ -124,10 +128,6 @@ fn make_datetime(
microsecond: u32,
tzinfo: Option<&PyTzInfo>,
) -> PyResult<Py<PyDateTime>> {
let tzi: PyObject = match tzinfo {
Some(t) => t.to_object(py),
None => py.None(),
};
PyDateTime::new(
py,
year,
@ -137,7 +137,7 @@ fn make_datetime(
minute,
second,
microsecond,
&tzi,
tzinfo.map(|o| (o.to_object(py))).as_ref(),
)
}

View File

@ -107,6 +107,29 @@ fn test_delta_check() {
assert_check_only!(PyDelta_Check, sub_sub_obj);
}
#[test]
#[cfg(Py_3)]
fn test_datetime_utc() {
let gil = Python::acquire_gil();
let py = gil.python();
let datetime = py.import("datetime").map_err(|e| e.print(py)).unwrap();
let timezone = datetime.get("timezone").unwrap();
let utc = timezone.getattr("utc").unwrap().to_object(py);
let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap();
let locals = PyDict::new(py);
locals.set_item("dt", dt).unwrap();
let offset: f32 = py
.eval("dt.utcoffset().total_seconds()", None, Some(locals))
.unwrap()
.extract()
.unwrap();
assert_eq!(offset, 0f32);
}
#[cfg(Py_3_6)]
#[test]
fn test_pydate_out_of_bounds() {