From c49bbe4549bc86f79cd12f6223804a71dfe3b575 Mon Sep 17 00:00:00 2001 From: Paul Ganssle Date: Sun, 8 Apr 2018 15:30:29 -0400 Subject: [PATCH] Add PyDateTime::from_timestamp --- src/objects/datetime.rs | 10 ++++++++++ tests/rustapi_module/src/lib.rs | 15 +++++++++++++++ tests/rustapi_module/tests/test_datetime.py | 20 +++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/objects/datetime.rs b/src/objects/datetime.rs index b594dcf2..0e8821f8 100644 --- a/src/objects/datetime.rs +++ b/src/objects/datetime.rs @@ -60,6 +60,16 @@ impl PyDateTime { Py::from_owned_ptr_or_err(py, ptr) } } + + pub fn from_timestamp(py: Python, args: &PyObject, kwargs: &PyObject) -> + PyResult> { + + unsafe { + let ptr = PyDateTimeAPI.DateTime_FromTimestamp.unwrap() + (PyDateTimeAPI.DateTimeType, args.as_ptr(), kwargs.as_ptr()); + Py::from_owned_ptr_or_err(py, ptr) + } + } } // datetime.time diff --git a/tests/rustapi_module/src/lib.rs b/tests/rustapi_module/src/lib.rs index 20d31aa0..ca51bab1 100644 --- a/tests/rustapi_module/src/lib.rs +++ b/tests/rustapi_module/src/lib.rs @@ -4,6 +4,7 @@ extern crate pyo3; use pyo3::{py, Py, Python, PyModule, PyResult}; use pyo3::{ToPyObject}; use pyo3::prelude::{PyObject}; +use pyo3::prelude::{PyTuple, PyDict}; use pyo3::prelude::{PyDate, PyTime, PyDateTime, PyDelta, PyTzInfo}; @@ -50,5 +51,19 @@ fn init_mod(py: Python, m: &PyModule) -> PyResult<()> { PyDateTime::new(py, year, month, day, hour, minute, second, microsecond, &tzi) } + #[pyfn(m, "datetime_from_timestamp")] + fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult> { + let timestamp : PyObject = ts.to_object(py); + let tzi : PyObject = match tz { + Some(t) => t.to_object(py), + None => py.None() + }; + + let args = PyTuple::new(py, &[timestamp, tzi]); + let kwargs = PyDict::new(py); + + PyDateTime::from_timestamp(py, &args.to_object(py), &kwargs.to_object(py)) + } + Ok(()) } diff --git a/tests/rustapi_module/tests/test_datetime.py b/tests/rustapi_module/tests/test_datetime.py index b48ce14b..5774ef41 100644 --- a/tests/rustapi_module/tests/test_datetime.py +++ b/tests/rustapi_module/tests/test_datetime.py @@ -5,7 +5,7 @@ import datetime as pdt import pytest from hypothesis import given -from hypothesis.strategies import dates +from hypothesis.strategies import dates, datetimes # Constants UTC = pdt.timezone.utc @@ -19,7 +19,7 @@ MIN_MICROSECONDS = int(pdt.timedelta.min.total_seconds() * 1e6) # Helper functions def get_timestamp(dt): - return int(dt.timestamp()) + return dt.timestamp() # Tests @@ -35,7 +35,7 @@ def test_invalid_date_fails(): @given(d=dates()) def test_date_from_timestamp(d): ts = get_timestamp(pdt.datetime.combine(d, pdt.time(0))) - assert rdt.date_from_timestamp(ts) == pdt.date.fromtimestamp(ts) + assert rdt.date_from_timestamp(int(ts)) == pdt.date.fromtimestamp(ts) @pytest.mark.parametrize('args, kwargs', [ @@ -111,6 +111,20 @@ def test_datetime_typeerror(): rdt.make_datetime('2011', 1, 1, 0, 0, 0, 0) +@given(dt=datetimes()) +def test_datetime_from_timestamp(dt): + ts = get_timestamp(dt) + assert rdt.datetime_from_timestamp(ts) == pdt.datetime.fromtimestamp(ts) + + +def test_datetime_from_timestamp_tzinfo(): + d1 = rdt.datetime_from_timestamp(0, tz=UTC) + d2 = rdt.datetime_from_timestamp(0, tz=UTC) + + assert d1 == d2 + assert d1.tzinfo is d2.tzinfo + + @pytest.mark.parametrize('args', [ (0, 0, 0), (1, 0, 0),