1//! FFI bindings to the functions and structs defined in `datetime.h`
2//!
3//! This is the unsafe thin wrapper around the [CPython C API](https://docs.python.org/3/c-api/datetime.html),
4//! and covers the various date and time related objects in the Python `datetime`
5//! standard library module.
6//!
7//! A note regarding PyPy (cpyext) support:
8//!
9//! Support for `PyDateTime_CAPI` is limited as of PyPy 7.0.0.
10//! `DateTime_FromTimestamp` and `Date_FromTimestamp` are currently not supported.
11
12use crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE};
13use std::cell::UnsafeCell;
14use std::os::raw::{c_char, c_int};
15use std::ptr;
16#[cfg(not(PyPy))]
17use {
18 crate::{PyCapsule_Import, Py_hash_t},
19 std::ffi::CString,
20 std::os::raw::c_uchar,
21};
22
23// Type struct wrappers
24const _PyDateTime_DATE_DATASIZE: usize = 4;
25const _PyDateTime_TIME_DATASIZE: usize = 6;
26const _PyDateTime_DATETIME_DATASIZE: usize = 10;
27
28#[repr(C)]
29#[derive(Debug, Copy, Clone)]
30/// Structure representing a `datetime.timedelta`.
31pub struct PyDateTime_Delta {
32 pub ob_base: PyObject,
33 #[cfg(not(PyPy))]
34 pub hashcode: Py_hash_t,
35 pub days: c_int,
36 pub seconds: c_int,
37 pub microseconds: c_int,
38}
39
40// skipped non-limited PyDateTime_TZInfo
41// skipped non-limited _PyDateTime_BaseTZInfo
42
43#[cfg(not(PyPy))]
44#[repr(C)]
45#[derive(Debug, Copy, Clone)]
46/// Structure representing a `datetime.time` without a `tzinfo` member.
47pub struct _PyDateTime_BaseTime {
48 pub ob_base: PyObject,
49 #[cfg(not(PyPy))]
50 pub hashcode: Py_hash_t,
51 pub hastzinfo: c_char,
52 #[cfg(not(PyPy))]
53 pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],
54}
55
56#[repr(C)]
57#[derive(Debug, Copy, Clone)]
58/// Structure representing a `datetime.time`.
59pub struct PyDateTime_Time {
60 pub ob_base: PyObject,
61 #[cfg(not(PyPy))]
62 pub hashcode: Py_hash_t,
63 pub hastzinfo: c_char,
64 #[cfg(not(PyPy))]
65 pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],
66 #[cfg(not(PyPy))]
67 pub fold: c_uchar,
68 /// # Safety
69 ///
70 /// Care should be taken when reading this field. If the time does not have a
71 /// tzinfo then CPython may allocate as a `_PyDateTime_BaseTime` without this field.
72 pub tzinfo: *mut PyObject,
73}
74
75#[repr(C)]
76#[derive(Debug, Copy, Clone)]
77/// Structure representing a `datetime.date`
78pub struct PyDateTime_Date {
79 pub ob_base: PyObject,
80 #[cfg(not(PyPy))]
81 pub hashcode: Py_hash_t,
82 #[cfg(not(PyPy))]
83 pub hastzinfo: c_char,
84 #[cfg(not(PyPy))]
85 pub data: [c_uchar; _PyDateTime_DATE_DATASIZE],
86}
87
88#[cfg(not(PyPy))]
89#[repr(C)]
90#[derive(Debug, Copy, Clone)]
91/// Structure representing a `datetime.datetime` without a `tzinfo` member.
92pub struct _PyDateTime_BaseDateTime {
93 pub ob_base: PyObject,
94 #[cfg(not(PyPy))]
95 pub hashcode: Py_hash_t,
96 pub hastzinfo: c_char,
97 #[cfg(not(PyPy))]
98 pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],
99}
100
101#[repr(C)]
102#[derive(Debug, Copy, Clone)]
103/// Structure representing a `datetime.datetime`.
104pub struct PyDateTime_DateTime {
105 pub ob_base: PyObject,
106 #[cfg(not(PyPy))]
107 pub hashcode: Py_hash_t,
108 pub hastzinfo: c_char,
109 #[cfg(not(PyPy))]
110 pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],
111 #[cfg(not(PyPy))]
112 pub fold: c_uchar,
113 /// # Safety
114 ///
115 /// Care should be taken when reading this field. If the time does not have a
116 /// tzinfo then CPython may allocate as a `_PyDateTime_BaseDateTime` without this field.
117 pub tzinfo: *mut PyObject,
118}
119
120// skipped non-limited _PyDateTime_HAS_TZINFO
121
122// Accessor functions for PyDateTime_Date and PyDateTime_DateTime
123#[inline]
124#[cfg(not(PyPy))]
125/// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`.
126/// Returns a signed integer greater than 0.
127pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
128 // This should work for Date or DateTime
129 let d: PyDateTime_Date = *(o as *mut PyDateTime_Date);
130 c_int::from(d.data[0]) << 8 | c_int::from(d.data[1])
131}
132
133#[inline]
134#[cfg(not(PyPy))]
135/// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`.
136/// Returns a signed integer in the range `[1, 12]`.
137pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {
138 let d: PyDateTime_Date = *(o as *mut PyDateTime_Date);
139 c_int::from(d.data[2])
140}
141
142#[inline]
143#[cfg(not(PyPy))]
144/// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`.
145/// Returns a signed integer in the interval `[1, 31]`.
146pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {
147 let d: PyDateTime_Date = *(o as *mut PyDateTime_Date);
148 c_int::from(d.data[3])
149}
150
151// Accessor macros for times
152#[cfg(not(PyPy))]
153macro_rules! _PyDateTime_GET_HOUR {
154 ($o: expr, $offset:expr) => {
155 c_int::from((*$o).data[$offset + 0])
156 };
157}
158
159#[cfg(not(PyPy))]
160macro_rules! _PyDateTime_GET_MINUTE {
161 ($o: expr, $offset:expr) => {
162 c_int::from((*$o).data[$offset + 1])
163 };
164}
165
166#[cfg(not(PyPy))]
167macro_rules! _PyDateTime_GET_SECOND {
168 ($o: expr, $offset:expr) => {
169 c_int::from((*$o).data[$offset + 2])
170 };
171}
172
173#[cfg(not(PyPy))]
174macro_rules! _PyDateTime_GET_MICROSECOND {
175 ($o: expr, $offset:expr) => {
176 (c_int::from((*$o).data[$offset + 3]) << 16)
177 | (c_int::from((*$o).data[$offset + 4]) << 8)
178 | (c_int::from((*$o).data[$offset + 5]))
179 };
180}
181
182#[cfg(not(PyPy))]
183macro_rules! _PyDateTime_GET_FOLD {
184 ($o: expr) => {
185 (*$o).fold
186 };
187}
188
189#[cfg(not(PyPy))]
190macro_rules! _PyDateTime_GET_TZINFO {
191 ($o: expr) => {
192 if (*$o).hastzinfo != 0 {
193 (*$o).tzinfo
194 } else {
195 $crate::Py_None()
196 }
197 };
198}
199
200// Accessor functions for DateTime
201#[inline]
202#[cfg(not(PyPy))]
203/// Retrieve the hour component of a `PyDateTime_DateTime`.
204/// Returns a signed integer in the interval `[0, 23]`
205pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {
206 _PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
207}
208
209#[inline]
210#[cfg(not(PyPy))]
211/// Retrieve the minute component of a `PyDateTime_DateTime`.
212/// Returns a signed integer in the interval `[0, 59]`
213pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {
214 _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
215}
216
217#[inline]
218#[cfg(not(PyPy))]
219/// Retrieve the second component of a `PyDateTime_DateTime`.
220/// Returns a signed integer in the interval `[0, 59]`
221pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {
222 _PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
223}
224
225#[inline]
226#[cfg(not(PyPy))]
227/// Retrieve the microsecond component of a `PyDateTime_DateTime`.
228/// Returns a signed integer in the interval `[0, 999999]`
229pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {
230 _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
231}
232
233#[inline]
234#[cfg(not(PyPy))]
235/// Retrieve the fold component of a `PyDateTime_DateTime`.
236/// Returns a signed integer in the interval `[0, 1]`
237pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar {
238 _PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime)
239}
240
241#[inline]
242#[cfg(not(PyPy))]
243/// Retrieve the tzinfo component of a `PyDateTime_DateTime`.
244/// Returns a pointer to a `PyObject` that should be either NULL or an instance
245/// of a `datetime.tzinfo` subclass.
246pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
247 _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime)
248}
249
250// Accessor functions for Time
251#[inline]
252#[cfg(not(PyPy))]
253/// Retrieve the hour component of a `PyDateTime_Time`.
254/// Returns a signed integer in the interval `[0, 23]`
255pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {
256 _PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0)
257}
258
259#[inline]
260#[cfg(not(PyPy))]
261/// Retrieve the minute component of a `PyDateTime_Time`.
262/// Returns a signed integer in the interval `[0, 59]`
263pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {
264 _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0)
265}
266
267#[inline]
268#[cfg(not(PyPy))]
269/// Retrieve the second component of a `PyDateTime_DateTime`.
270/// Returns a signed integer in the interval `[0, 59]`
271pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {
272 _PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0)
273}
274
275#[inline]
276#[cfg(not(PyPy))]
277/// Retrieve the microsecond component of a `PyDateTime_DateTime`.
278/// Returns a signed integer in the interval `[0, 999999]`
279pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {
280 _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0)
281}
282
283#[cfg(not(PyPy))]
284#[inline]
285/// Retrieve the fold component of a `PyDateTime_Time`.
286/// Returns a signed integer in the interval `[0, 1]`
287pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar {
288 _PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time)
289}
290
291#[inline]
292#[cfg(not(PyPy))]
293/// Retrieve the tzinfo component of a `PyDateTime_Time`.
294/// Returns a pointer to a `PyObject` that should be either NULL or an instance
295/// of a `datetime.tzinfo` subclass.
296pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
297 _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time)
298}
299
300// Accessor functions
301#[cfg(not(PyPy))]
302macro_rules! _access_field {
303 ($obj:expr, $type: ident, $field:ident) => {
304 (*($obj as *mut $type)).$field
305 };
306}
307
308// Accessor functions for PyDateTime_Delta
309#[cfg(not(PyPy))]
310macro_rules! _access_delta_field {
311 ($obj:expr, $field:ident) => {
312 _access_field!($obj, PyDateTime_Delta, $field)
313 };
314}
315
316#[inline]
317#[cfg(not(PyPy))]
318/// Retrieve the days component of a `PyDateTime_Delta`.
319///
320/// Returns a signed integer in the interval [-999999999, 999999999].
321///
322/// Note: This retrieves a component from the underlying structure, it is *not*
323/// a representation of the total duration of the structure.
324pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
325 _access_delta_field!(o, days)
326}
327
328#[inline]
329#[cfg(not(PyPy))]
330/// Retrieve the seconds component of a `PyDateTime_Delta`.
331///
332/// Returns a signed integer in the interval [0, 86399].
333///
334/// Note: This retrieves a component from the underlying structure, it is *not*
335/// a representation of the total duration of the structure.
336pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
337 _access_delta_field!(o, seconds)
338}
339
340#[inline]
341#[cfg(not(PyPy))]
342/// Retrieve the seconds component of a `PyDateTime_Delta`.
343///
344/// Returns a signed integer in the interval [0, 999999].
345///
346/// Note: This retrieves a component from the underlying structure, it is *not*
347/// a representation of the total duration of the structure.
348pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
349 _access_delta_field!(o, microseconds)
350}
351
352#[cfg(PyPy)]
353extern "C" {
354 // skipped _PyDateTime_HAS_TZINFO (not in PyPy)
355 #[link_name = "PyPyDateTime_GET_YEAR"]
356 pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int;
357 #[link_name = "PyPyDateTime_GET_MONTH"]
358 pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int;
359 #[link_name = "PyPyDateTime_GET_DAY"]
360 pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int;
361
362 #[link_name = "PyPyDateTime_DATE_GET_HOUR"]
363 pub fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int;
364 #[link_name = "PyPyDateTime_DATE_GET_MINUTE"]
365 pub fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int;
366 #[link_name = "PyPyDateTime_DATE_GET_SECOND"]
367 pub fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int;
368 #[link_name = "PyPyDateTime_DATE_GET_MICROSECOND"]
369 pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int;
370 #[link_name = "PyPyDateTime_GET_FOLD"]
371 pub fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int;
372 // skipped PyDateTime_DATE_GET_TZINFO (not in PyPy)
373
374 #[link_name = "PyPyDateTime_TIME_GET_HOUR"]
375 pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int;
376 #[link_name = "PyPyDateTime_TIME_GET_MINUTE"]
377 pub fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int;
378 #[link_name = "PyPyDateTime_TIME_GET_SECOND"]
379 pub fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int;
380 #[link_name = "PyPyDateTime_TIME_GET_MICROSECOND"]
381 pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int;
382 #[link_name = "PyPyDateTime_TIME_GET_FOLD"]
383 pub fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int;
384 // skipped PyDateTime_TIME_GET_TZINFO (not in PyPy)
385
386 #[link_name = "PyPyDateTime_DELTA_GET_DAYS"]
387 pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int;
388 #[link_name = "PyPyDateTime_DELTA_GET_SECONDS"]
389 pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int;
390 #[link_name = "PyPyDateTime_DELTA_GET_MICROSECONDS"]
391 pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int;
392}
393
394#[repr(C)]
395#[derive(Debug, Copy, Clone)]
396pub struct PyDateTime_CAPI {
397 pub DateType: *mut PyTypeObject,
398 pub DateTimeType: *mut PyTypeObject,
399 pub TimeType: *mut PyTypeObject,
400 pub DeltaType: *mut PyTypeObject,
401 pub TZInfoType: *mut PyTypeObject,
402 pub TimeZone_UTC: *mut PyObject,
403 pub Date_FromDate: unsafe extern "C" fn(
404 year: c_int,
405 month: c_int,
406 day: c_int,
407 cls: *mut PyTypeObject,
408 ) -> *mut PyObject,
409 pub DateTime_FromDateAndTime: unsafe extern "C" fn(
410 year: c_int,
411 month: c_int,
412 day: c_int,
413 hour: c_int,
414 minute: c_int,
415 second: c_int,
416 microsecond: c_int,
417 tzinfo: *mut PyObject,
418 cls: *mut PyTypeObject,
419 ) -> *mut PyObject,
420 pub Time_FromTime: unsafe extern "C" fn(
421 hour: c_int,
422 minute: c_int,
423 second: c_int,
424 microsecond: c_int,
425 tzinfo: *mut PyObject,
426 cls: *mut PyTypeObject,
427 ) -> *mut PyObject,
428 pub Delta_FromDelta: unsafe extern "C" fn(
429 days: c_int,
430 seconds: c_int,
431 microseconds: c_int,
432 normalize: c_int,
433 cls: *mut PyTypeObject,
434 ) -> *mut PyObject,
435 pub TimeZone_FromTimeZone:
436 unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject,
437
438 pub DateTime_FromTimestamp: unsafe extern "C" fn(
439 cls: *mut PyTypeObject,
440 args: *mut PyObject,
441 kwargs: *mut PyObject,
442 ) -> *mut PyObject,
443 pub Date_FromTimestamp:
444 unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject,
445 pub DateTime_FromDateAndTimeAndFold: unsafe extern "C" fn(
446 year: c_int,
447 month: c_int,
448 day: c_int,
449 hour: c_int,
450 minute: c_int,
451 second: c_int,
452 microsecond: c_int,
453 tzinfo: *mut PyObject,
454 fold: c_int,
455 cls: *mut PyTypeObject,
456 ) -> *mut PyObject,
457 pub Time_FromTimeAndFold: unsafe extern "C" fn(
458 hour: c_int,
459 minute: c_int,
460 second: c_int,
461 microsecond: c_int,
462 tzinfo: *mut PyObject,
463 fold: c_int,
464 cls: *mut PyTypeObject,
465 ) -> *mut PyObject,
466}
467
468// Python already shares this object between threads, so it's no more evil for us to do it too!
469unsafe impl Sync for PyDateTime_CAPI {}
470
471/// Returns a pointer to a `PyDateTime_CAPI` instance
472///
473/// # Note
474/// This function will return a null pointer until
475/// `PyDateTime_IMPORT` is called
476#[inline]
477pub unsafe fn PyDateTimeAPI() -> *mut PyDateTime_CAPI {
478 *PyDateTimeAPI_impl.0.get()
479}
480
481#[inline]
482pub unsafe fn PyDateTime_TimeZone_UTC() -> *mut PyObject {
483 (*PyDateTimeAPI()).TimeZone_UTC
484}
485
486/// Populates the `PyDateTimeAPI` object
487pub unsafe fn PyDateTime_IMPORT() {
488 // PyPy expects the C-API to be initialized via PyDateTime_Import, so trying to use
489 // `PyCapsule_Import` will behave unexpectedly in pypy.
490 #[cfg(PyPy)]
491 let py_datetime_c_api = PyDateTime_Import();
492
493 #[cfg(not(PyPy))]
494 let py_datetime_c_api: *mut PyDateTime_CAPI = {
495 // PyDateTime_CAPSULE_NAME is a macro in C
496 let PyDateTime_CAPSULE_NAME: CString = CString::new("datetime.datetime_CAPI").unwrap();
497
498 PyCapsule_Import(name:PyDateTime_CAPSULE_NAME.as_ptr(), no_block:1) as *mut PyDateTime_CAPI
499 };
500
501 *PyDateTimeAPI_impl.0.get() = py_datetime_c_api;
502}
503
504// skipped non-limited PyDateTime_TimeZone_UTC
505
506/// Type Check macros
507///
508/// These are bindings around the C API typecheck macros, all of them return
509/// `1` if True and `0` if False. In all type check macros, the argument (`op`)
510/// must not be `NULL`.
511#[inline]
512/// Check if `op` is a `PyDateTimeAPI.DateType` or subtype.
513pub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int {
514 PyObject_TypeCheck(ob:op, (*PyDateTimeAPI()).DateType) as c_int
515}
516
517#[inline]
518/// Check if `op`'s type is exactly `PyDateTimeAPI.DateType`.
519pub unsafe fn PyDate_CheckExact(op: *mut PyObject) -> c_int {
520 (Py_TYPE(ob:op) == (*PyDateTimeAPI()).DateType) as c_int
521}
522
523#[inline]
524/// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype.
525pub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int {
526 PyObject_TypeCheck(ob:op, (*PyDateTimeAPI()).DateTimeType) as c_int
527}
528
529#[inline]
530/// Check if `op`'s type is exactly `PyDateTimeAPI.DateTimeType`.
531pub unsafe fn PyDateTime_CheckExact(op: *mut PyObject) -> c_int {
532 (Py_TYPE(ob:op) == (*PyDateTimeAPI()).DateTimeType) as c_int
533}
534
535#[inline]
536/// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype.
537pub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int {
538 PyObject_TypeCheck(ob:op, (*PyDateTimeAPI()).TimeType) as c_int
539}
540
541#[inline]
542/// Check if `op`'s type is exactly `PyDateTimeAPI.TimeType`.
543pub unsafe fn PyTime_CheckExact(op: *mut PyObject) -> c_int {
544 (Py_TYPE(ob:op) == (*PyDateTimeAPI()).TimeType) as c_int
545}
546
547#[inline]
548/// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype.
549pub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int {
550 PyObject_TypeCheck(ob:op, (*PyDateTimeAPI()).DeltaType) as c_int
551}
552
553#[inline]
554/// Check if `op`'s type is exactly `PyDateTimeAPI.DeltaType`.
555pub unsafe fn PyDelta_CheckExact(op: *mut PyObject) -> c_int {
556 (Py_TYPE(ob:op) == (*PyDateTimeAPI()).DeltaType) as c_int
557}
558
559#[inline]
560/// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype.
561pub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int {
562 PyObject_TypeCheck(ob:op, (*PyDateTimeAPI()).TZInfoType) as c_int
563}
564
565#[inline]
566/// Check if `op`'s type is exactly `PyDateTimeAPI.TZInfoType`.
567pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int {
568 (Py_TYPE(ob:op) == (*PyDateTimeAPI()).TZInfoType) as c_int
569}
570
571// skipped non-limited PyDate_FromDate
572// skipped non-limited PyDateTime_FromDateAndTime
573// skipped non-limited PyDateTime_FromDateAndTimeAndFold
574// skipped non-limited PyTime_FromTime
575// skipped non-limited PyTime_FromTimeAndFold
576// skipped non-limited PyDelta_FromDSU
577
578pub unsafe fn PyTimeZone_FromOffset(offset: *mut PyObject) -> *mut PyObject {
579 ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, std::ptr::null_mut())
580}
581
582pub unsafe fn PyTimeZone_FromOffsetAndName(
583 offset: *mut PyObject,
584 name: *mut PyObject,
585) -> *mut PyObject {
586 ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, name)
587}
588
589#[cfg(not(PyPy))]
590pub unsafe fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject {
591 let f: unsafe fn(*mut PyTypeObject, …) -> … = (*PyDateTimeAPI()).DateTime_FromTimestamp;
592 f((*PyDateTimeAPI()).DateTimeType, args, std::ptr::null_mut())
593}
594
595#[cfg(not(PyPy))]
596pub unsafe fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject {
597 let f: unsafe fn(*mut PyTypeObject, …) -> … = (*PyDateTimeAPI()).Date_FromTimestamp;
598 f((*PyDateTimeAPI()).DateType, args)
599}
600
601#[cfg(PyPy)]
602extern "C" {
603 #[link_name = "PyPyDate_FromTimestamp"]
604 pub fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject;
605 #[link_name = "PyPyDateTime_FromTimestamp"]
606 pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject;
607}
608
609#[cfg(PyPy)]
610extern "C" {
611 #[link_name = "_PyPyDateTime_Import"]
612 pub fn PyDateTime_Import() -> *mut PyDateTime_CAPI;
613}
614
615// Rust specific implementation details
616
617struct PyDateTimeAPISingleton(UnsafeCell<*mut PyDateTime_CAPI>);
618unsafe impl Sync for PyDateTimeAPISingleton {}
619
620static PyDateTimeAPI_impl: PyDateTimeAPISingleton =
621 PyDateTimeAPISingleton(UnsafeCell::new(ptr::null_mut()));
622