Merge pull request #232 from pganssle/update-datetime-docs
Add documentation and changelog for datetime bindings
This commit is contained in:
commit
78d3d11d12
|
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
* `#[pyclass]` objects can now be returned from rust functions
|
||||
* `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226)
|
||||
* `PyDict::from_sequence()`, equivalent to `dict([(key, val), ...])`
|
||||
* Bindings for the `datetime` standard library types: `PyDate`, `PyTime`, `PyDateTime`, `PyTzInfo`, `PyDelta` with associated `ffi` types, by pganssle [#200](https://github.com/PyO3/pyo3/pull/200).
|
||||
|
||||
### Removed
|
||||
* Removed most entries from the prelude. The new prelude is small and clear.
|
||||
|
@ -27,7 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|||
|
||||
### Fixed
|
||||
|
||||
* Added an explenation that the GIL can temporarily be released even while holding a GILGuard.
|
||||
* Added an explanation that the GIL can temporarily be released even while holding a GILGuard.
|
||||
* Lots of clippy errors
|
||||
* Fix segfault on calling an unknown method on a PyObject
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#![cfg_attr(feature="cargo-clippy", allow(type_complexity))]
|
||||
|
||||
//! FFI bindings to the functions and structs defined in `datetime.h`
|
||||
//!
|
||||
//! This is the unsafe thin wrapper around the [CPython C API](https://docs.python.org/3/c-api/datetime.html),
|
||||
//! and covers the various date and time related objects in the Python `datetime`
|
||||
//! standard library module.
|
||||
use ffi::PyCapsule_Import;
|
||||
use ffi::Py_hash_t;
|
||||
use ffi::{PyObject, PyTypeObject};
|
||||
|
@ -101,6 +105,7 @@ const _PyDateTime_DATETIME_DATASIZE: usize = 10;
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Structure representing a `datetime.date`
|
||||
pub struct PyDateTime_Date {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
|
@ -110,6 +115,7 @@ pub struct PyDateTime_Date {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Structure representing a `datetime.time`
|
||||
pub struct PyDateTime_Time {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
|
@ -122,6 +128,7 @@ pub struct PyDateTime_Time {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Structure representing a `datetime.datetime`
|
||||
pub struct PyDateTime_DateTime {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
|
@ -134,6 +141,7 @@ pub struct PyDateTime_DateTime {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// Structure representing a `datetime.timedelta`
|
||||
pub struct PyDateTime_Delta {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
|
@ -188,6 +196,13 @@ impl Deref for PyDateTimeAPI {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
/// Populates the `PyDateTimeAPI` object
|
||||
///
|
||||
/// Unlike in C, this does *not* need to be actively invoked in Rust, which
|
||||
/// will populate the `PyDateTimeAPI` struct automatically on first use.
|
||||
/// Use this function only if you want to eagerly load the datetime module,
|
||||
/// such as if you do not want the first call to a datetime function to be
|
||||
/// slightly slower than subsequent calls.
|
||||
pub unsafe fn PyDateTime_IMPORT() -> &'static PyDateTime_CAPI {
|
||||
// PyDateTime_CAPSULE_NAME is a macro in C
|
||||
let PyDateTime_CAPSULE_NAME = CString::new("datetime.datetime_CAPI").unwrap();
|
||||
|
@ -201,62 +216,73 @@ pub unsafe fn PyDateTime_IMPORT() -> &'static PyDateTime_CAPI {
|
|||
&(*PY_DATETIME_API_UNSAFE_CACHE)
|
||||
}
|
||||
|
||||
//
|
||||
// Type Check macros
|
||||
//
|
||||
/// Type Check macros
|
||||
///
|
||||
/// These are bindings around the C API typecheck macros, all of them return
|
||||
/// `1` if True and `0` if False. In all type check macros, the argument (`op`)
|
||||
/// must not be `NULL`.
|
||||
#[inline]
|
||||
/// Check if `op` is a `PyDateTimeAPI.DateType` or subtype.
|
||||
pub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DateType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op`'s type is exactly `PyDateTimeAPI.DateType`.
|
||||
pub unsafe fn PyDate_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.DateType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype.
|
||||
pub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op`'s type is exactly `PyDateTimeAPI.DateTimeType`.
|
||||
pub unsafe fn PyDateTime_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.DateTimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype.
|
||||
pub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.TimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op`'s type is exactly `PyDateTimeAPI.TimeType`.
|
||||
pub unsafe fn PyTime_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.TimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype.
|
||||
pub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op`'s type is exactly `PyDateTimeAPI.DeltaType`.
|
||||
pub unsafe fn PyDelta_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.DeltaType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype.
|
||||
pub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Check if `op`'s type is exactly `PyDateTimeAPI.TZInfoType`.
|
||||
pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.TZInfoType) as c_int
|
||||
}
|
||||
|
||||
//
|
||||
// Accessor functions
|
||||
//
|
||||
/// Accessor functions
|
||||
///
|
||||
macro_rules! _access_field {
|
||||
($obj:expr, $type: ident, $field:tt) => {
|
||||
(*($obj as *mut $type)).$field
|
||||
|
@ -265,6 +291,8 @@ macro_rules! _access_field {
|
|||
|
||||
// Accessor functions for PyDateTime_Date and PyDateTime_DateTime
|
||||
#[inline]
|
||||
/// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer greater than 0.
|
||||
pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
|
||||
// This should work for Date or DateTime
|
||||
let d = *(o as *mut PyDateTime_Date);
|
||||
|
@ -272,12 +300,16 @@ pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the range `[1, 12]`.
|
||||
pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {
|
||||
let d = *(o as *mut PyDateTime_Date);
|
||||
c_int::from(d.data[2])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[1, 31]`.
|
||||
pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {
|
||||
let d = *(o as *mut PyDateTime_Date);
|
||||
c_int::from(d.data[3])
|
||||
|
@ -325,64 +357,94 @@ macro_rules! _PyDateTime_GET_TZINFO {
|
|||
|
||||
// Accessor functions for DateTime
|
||||
#[inline]
|
||||
/// Retrieve the hour component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 23]`
|
||||
pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the minute component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 59]`
|
||||
pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the second component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 59]`
|
||||
pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the microsecond component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 999999]`
|
||||
pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[inline]
|
||||
/// Retrieve the fold component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 1]`
|
||||
///
|
||||
/// Added in version Python 3.6
|
||||
pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar {
|
||||
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the tzinfo component of a `PyDateTime_DateTime`.
|
||||
/// Returns a pointer to a `PyObject` that should be either NULL or an instance
|
||||
/// of a `datetime.tzinfo` subclass.
|
||||
pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
|
||||
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime)
|
||||
}
|
||||
|
||||
// Accessor functions for Time
|
||||
#[inline]
|
||||
/// Retrieve the hour component of a `PyDateTime_Time`.
|
||||
/// Returns a signed integer in the interval `[0, 23]`
|
||||
pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the minute component of a `PyDateTime_Time`.
|
||||
/// Returns a signed integer in the interval `[0, 59]`
|
||||
pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the second component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 59]`
|
||||
pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the microsecond component of a `PyDateTime_DateTime`.
|
||||
/// Returns a signed integer in the interval `[0, 999999]`
|
||||
pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[inline]
|
||||
/// Retrieve the fold component of a `PyDateTime_Time`.
|
||||
/// Returns a signed integer in the interval `[0, 1]`
|
||||
///
|
||||
/// Added in version Python 3.6
|
||||
pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar {
|
||||
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the tzinfo component of a `PyDateTime_Time`.
|
||||
/// Returns a pointer to a `PyObject` that should be either NULL or an instance
|
||||
/// of a `datetime.tzinfo` subclass.
|
||||
pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
|
||||
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time)
|
||||
}
|
||||
|
@ -395,16 +457,34 @@ macro_rules! _access_delta_field {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the days component of a `PyDateTime_Delta`.
|
||||
///
|
||||
/// Returns a signed integer in the interval [-999999999, 999999999].
|
||||
///
|
||||
/// Note: This retrieves a component from the underlying structure, it is *not*
|
||||
/// a representation of the total duration of the structure.
|
||||
pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
|
||||
_access_delta_field!(o, days)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the seconds component of a `PyDateTime_Delta`.
|
||||
///
|
||||
/// Returns a signed integer in the interval [0, 86399].
|
||||
///
|
||||
/// Note: This retrieves a component from the underlying structure, it is *not*
|
||||
/// a representation of the total duration of the structure.
|
||||
pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
|
||||
_access_delta_field!(o, seconds)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Retrieve the seconds component of a `PyDateTime_Delta`.
|
||||
///
|
||||
/// Returns a signed integer in the interval [0, 999999].
|
||||
///
|
||||
/// Note: This retrieves a component from the underlying structure, it is *not*
|
||||
/// a representation of the total duration of the structure.
|
||||
pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
|
||||
_access_delta_field!(o, microseconds)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
//! Safe Rust wrappers for types defined in the Python `datetime` library
|
||||
//!
|
||||
//! For more details about these types, see the [Python
|
||||
//! documentation](https://docs.python.org/3/library/datetime.html)
|
||||
use conversion::ToPyObject;
|
||||
use err::PyResult;
|
||||
use ffi;
|
||||
|
@ -28,19 +32,27 @@ use std::os::raw::c_int;
|
|||
use std::ptr;
|
||||
use types::PyTuple;
|
||||
|
||||
// Traits
|
||||
/// Access traits
|
||||
|
||||
/// Trait for accessing the date components of a struct containing a date.
|
||||
pub trait PyDateAccess {
|
||||
fn get_year(&self) -> i32;
|
||||
fn get_month(&self) -> u8;
|
||||
fn get_day(&self) -> u8;
|
||||
}
|
||||
|
||||
/// Trait for accessing the components of a struct containing a timedelta.
|
||||
///
|
||||
/// Note: These access the individual components of a (day, second,
|
||||
/// microsecond) representation of the delta, they are *not* intended as
|
||||
/// aliases for calculating the total duration in each of these units.
|
||||
pub trait PyDeltaAccess {
|
||||
fn get_days(&self) -> i32;
|
||||
fn get_seconds(&self) -> i32;
|
||||
fn get_microseconds(&self) -> i32;
|
||||
}
|
||||
|
||||
/// Trait for accessing the time components of a struct containing a time.
|
||||
pub trait PyTimeAccess {
|
||||
fn get_hour(&self) -> u8;
|
||||
fn get_minute(&self) -> u8;
|
||||
|
@ -50,7 +62,7 @@ pub trait PyTimeAccess {
|
|||
fn get_fold(&self) -> u8;
|
||||
}
|
||||
|
||||
// datetime.date bindings
|
||||
/// Bindings around `datetime.date`
|
||||
pub struct PyDate(PyObject);
|
||||
pyobject_native_type!(PyDate, PyDateTime_DateType, PyDate_Check);
|
||||
|
||||
|
@ -67,6 +79,9 @@ impl PyDate {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct a `datetime.date` from a POSIX timestamp
|
||||
///
|
||||
/// This is equivalent to `datetime.date.fromtimestamp`
|
||||
pub fn from_timestamp(py: Python, timestamp: i64) -> PyResult<Py<PyDate>> {
|
||||
let args = PyTuple::new(py, &[timestamp]);
|
||||
|
||||
|
@ -91,7 +106,7 @@ impl PyDateAccess for PyDate {
|
|||
}
|
||||
}
|
||||
|
||||
// datetime.datetime bindings
|
||||
/// Bindings for `datetime.datetime`
|
||||
pub struct PyDateTime(PyObject);
|
||||
pyobject_native_type!(PyDateTime, PyDateTime_DateTimeType, PyDateTime_Check);
|
||||
|
||||
|
@ -123,6 +138,9 @@ impl PyDateTime {
|
|||
}
|
||||
}
|
||||
|
||||
/// Construct a `datetime` object from a POSIX timestamp
|
||||
///
|
||||
/// This is equivalent to `datetime.datetime.from_timestamp`
|
||||
pub fn from_timestamp(
|
||||
py: Python,
|
||||
timestamp: f64,
|
||||
|
@ -185,7 +203,7 @@ impl PyTimeAccess for PyDateTime {
|
|||
}
|
||||
}
|
||||
|
||||
// datetime.time
|
||||
/// Bindings for `datetime.time`
|
||||
pub struct PyTime(PyObject);
|
||||
pyobject_native_type!(PyTime, PyDateTime_TimeType, PyTime_Check);
|
||||
|
||||
|
@ -212,6 +230,9 @@ impl PyTime {
|
|||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
/// Alternate constructor that takes a `fold` argument
|
||||
///
|
||||
/// First available in Python 3.6.
|
||||
pub fn new_with_fold(
|
||||
py: Python,
|
||||
hour: u8,
|
||||
|
@ -259,11 +280,13 @@ impl PyTimeAccess for PyTime {
|
|||
}
|
||||
}
|
||||
|
||||
// datetime.tzinfo bindings
|
||||
/// Bindings for `datetime.tzinfo`
|
||||
///
|
||||
/// This is an abstract base class and should not be constructed directly.
|
||||
pub struct PyTzInfo(PyObject);
|
||||
pyobject_native_type!(PyTzInfo, PyDateTime_TZInfoType, PyTZInfo_Check);
|
||||
|
||||
// datetime.timedelta bindings
|
||||
/// Bindings for `datetime.timedelta`
|
||||
pub struct PyDelta(PyObject);
|
||||
pyobject_native_type!(PyDelta, PyDateTime_DeltaType, PyDelta_Check);
|
||||
|
||||
|
|
Loading…
Reference in New Issue