Skip to content

Commit

Permalink
implement datetime traits for Py2
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Dec 20, 2023
1 parent fd2fc98 commit 31aad2e
Showing 1 changed file with 129 additions and 3 deletions.
132 changes: 129 additions & 3 deletions src/types/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ use crate::ffi::{
PyDateTime_TIME_GET_FOLD, PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND,
PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND,
};
use crate::ffi_ptr_ext::FfiPtrExt;
use crate::instance::PyNativeType;
use crate::types::any::PyAnyMethods;
use crate::types::PyTuple;
use crate::{AsPyPointer, IntoPy, Py, PyAny, Python};
use crate::{IntoPy, Py, Py2, PyAny, Python};
use std::os::raw::c_int;
#[cfg(feature = "chrono")]
use std::ptr;
Expand Down Expand Up @@ -169,6 +171,16 @@ pub trait PyTzInfoAccess {
fn get_tzinfo(&self) -> Option<&PyTzInfo>;
}

/// Trait for accessing the components of a struct containing a tzinfo.
pub(crate) trait PyTzInfoAccess2<'py> {
/// Returns the tzinfo (which may be None).
///
/// Implementations should conform to the upstream documentation:
/// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DATE_GET_TZINFO>
/// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_TIME_GET_TZINFO>
fn get_tzinfo(&self) -> Option<Py2<'py, PyTzInfo>>;
}

/// Bindings around `datetime.date`
#[repr(transparent)]
pub struct PyDate(PyAny);
Expand Down Expand Up @@ -211,6 +223,20 @@ impl PyDate {
}

impl PyDateAccess for PyDate {
fn get_year(&self) -> i32 {
Py2::<PyDate>::borrowed_from_gil_ref(&self).get_year()
}

fn get_month(&self) -> u8 {
Py2::<PyDate>::borrowed_from_gil_ref(&self).get_month()
}

fn get_day(&self) -> u8 {
Py2::<PyDate>::borrowed_from_gil_ref(&self).get_day()
}
}

impl PyDateAccess for Py2<'_, PyDate> {
fn get_year(&self) -> i32 {
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) }
}
Expand Down Expand Up @@ -325,6 +351,20 @@ impl PyDateTime {
}

impl PyDateAccess for PyDateTime {
fn get_year(&self) -> i32 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_year()
}

fn get_month(&self) -> u8 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_month()
}

fn get_day(&self) -> u8 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_day()
}
}

impl PyDateAccess for Py2<'_, PyDateTime> {
fn get_year(&self) -> i32 {
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) }
}
Expand All @@ -339,6 +379,28 @@ impl PyDateAccess for PyDateTime {
}

impl PyTimeAccess for PyDateTime {
fn get_hour(&self) -> u8 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_hour()
}

fn get_minute(&self) -> u8 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_minute()
}

fn get_second(&self) -> u8 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_second()
}

fn get_microsecond(&self) -> u32 {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_microsecond()
}

fn get_fold(&self) -> bool {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self).get_fold()
}
}

impl PyTimeAccess for Py2<'_, PyDateTime> {
fn get_hour(&self) -> u8 {
unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u8 }
}
Expand All @@ -362,10 +424,24 @@ impl PyTimeAccess for PyDateTime {

impl PyTzInfoAccess for PyDateTime {
fn get_tzinfo(&self) -> Option<&PyTzInfo> {
Py2::<PyDateTime>::borrowed_from_gil_ref(&self)
.get_tzinfo()
.map(Py2::into_gil_ref)
}
}

impl<'py> PyTzInfoAccess2<'py> for Py2<'py, PyDateTime> {
fn get_tzinfo(&self) -> Option<Py2<'py, PyTzInfo>> {
let ptr = self.as_ptr() as *mut ffi::PyDateTime_DateTime;
unsafe {
if (*ptr).hastzinfo != 0 {
Some(self.py().from_borrowed_ptr((*ptr).tzinfo))
Some(
(*ptr)
.tzinfo
.assume_borrowed(self.py())
.to_owned()
.downcast_into_unchecked(),
)
} else {
None
}
Expand Down Expand Up @@ -435,6 +511,28 @@ impl PyTime {
}

impl PyTimeAccess for PyTime {
fn get_hour(&self) -> u8 {
Py2::<PyTime>::borrowed_from_gil_ref(&self).get_hour()
}

fn get_minute(&self) -> u8 {
Py2::<PyTime>::borrowed_from_gil_ref(&self).get_minute()
}

fn get_second(&self) -> u8 {
Py2::<PyTime>::borrowed_from_gil_ref(&self).get_second()
}

fn get_microsecond(&self) -> u32 {
Py2::<PyTime>::borrowed_from_gil_ref(&self).get_microsecond()
}

fn get_fold(&self) -> bool {
Py2::<PyTime>::borrowed_from_gil_ref(&self).get_fold()
}
}

impl PyTimeAccess for Py2<'_, PyTime> {
fn get_hour(&self) -> u8 {
unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u8 }
}
Expand All @@ -458,10 +556,24 @@ impl PyTimeAccess for PyTime {

impl PyTzInfoAccess for PyTime {
fn get_tzinfo(&self) -> Option<&PyTzInfo> {
Py2::<PyTime>::borrowed_from_gil_ref(&self)
.get_tzinfo()
.map(Py2::into_gil_ref)
}
}

impl<'py> PyTzInfoAccess2<'py> for Py2<'py, PyTime> {
fn get_tzinfo(&self) -> Option<Py2<'py, PyTzInfo>> {
let ptr = self.as_ptr() as *mut ffi::PyDateTime_Time;
unsafe {
if (*ptr).hastzinfo != 0 {
Some(self.py().from_borrowed_ptr((*ptr).tzinfo))
Some(
(*ptr)
.tzinfo
.assume_borrowed(self.py())
.to_owned()
.downcast_into_unchecked(),
)
} else {
None
}
Expand Down Expand Up @@ -536,6 +648,20 @@ impl PyDelta {
}

impl PyDeltaAccess for PyDelta {
fn get_days(&self) -> i32 {
Py2::<PyDelta>::borrowed_from_gil_ref(&self).get_days()
}

fn get_seconds(&self) -> i32 {
Py2::<PyDelta>::borrowed_from_gil_ref(&self).get_seconds()
}

fn get_microseconds(&self) -> i32 {
Py2::<PyDelta>::borrowed_from_gil_ref(&self).get_microseconds()
}
}

impl PyDeltaAccess for Py2<'_, PyDelta> {
fn get_days(&self) -> i32 {
unsafe { PyDateTime_DELTA_GET_DAYS(self.as_ptr()) }
}
Expand Down

0 comments on commit 31aad2e

Please sign in to comment.