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 | |
12 | use crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE}; |
13 | use std::cell::UnsafeCell; |
14 | use std::os::raw::{c_char, c_int}; |
15 | use std::ptr; |
16 | #[cfg (not(PyPy))] |
17 | use { |
18 | crate::{PyCapsule_Import, Py_hash_t}, |
19 | std::ffi::CString, |
20 | std::os::raw::c_uchar, |
21 | }; |
22 | |
23 | // Type struct wrappers |
24 | const _PyDateTime_DATE_DATASIZE: usize = 4; |
25 | const _PyDateTime_TIME_DATASIZE: usize = 6; |
26 | const _PyDateTime_DATETIME_DATASIZE: usize = 10; |
27 | |
28 | #[repr (C)] |
29 | #[derive (Debug, Copy, Clone)] |
30 | /// Structure representing a `datetime.timedelta`. |
31 | pub 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. |
47 | pub 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`. |
59 | pub 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` |
78 | pub 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. |
92 | pub 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`. |
104 | pub 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. |
127 | pub 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]`. |
137 | pub 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]`. |
146 | pub 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))] |
153 | macro_rules! _PyDateTime_GET_HOUR { |
154 | ($o: expr, $offset:expr) => { |
155 | c_int::from((*$o).data[$offset + 0]) |
156 | }; |
157 | } |
158 | |
159 | #[cfg (not(PyPy))] |
160 | macro_rules! _PyDateTime_GET_MINUTE { |
161 | ($o: expr, $offset:expr) => { |
162 | c_int::from((*$o).data[$offset + 1]) |
163 | }; |
164 | } |
165 | |
166 | #[cfg (not(PyPy))] |
167 | macro_rules! _PyDateTime_GET_SECOND { |
168 | ($o: expr, $offset:expr) => { |
169 | c_int::from((*$o).data[$offset + 2]) |
170 | }; |
171 | } |
172 | |
173 | #[cfg (not(PyPy))] |
174 | macro_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))] |
183 | macro_rules! _PyDateTime_GET_FOLD { |
184 | ($o: expr) => { |
185 | (*$o).fold |
186 | }; |
187 | } |
188 | |
189 | #[cfg (not(PyPy))] |
190 | macro_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]` |
205 | pub 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]` |
213 | pub 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]` |
221 | pub 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]` |
229 | pub 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]` |
237 | pub 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. |
246 | pub 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]` |
255 | pub 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]` |
263 | pub 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]` |
271 | pub 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]` |
279 | pub 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]` |
287 | pub 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. |
296 | pub 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))] |
302 | macro_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))] |
310 | macro_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. |
324 | pub 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. |
336 | pub 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. |
348 | pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { |
349 | _access_delta_field!(o, microseconds) |
350 | } |
351 | |
352 | #[cfg (PyPy)] |
353 | extern "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)] |
396 | pub 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! |
469 | unsafe 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 ] |
477 | pub unsafe fn PyDateTimeAPI() -> *mut PyDateTime_CAPI { |
478 | *PyDateTimeAPI_impl.0.get() |
479 | } |
480 | |
481 | #[inline ] |
482 | pub unsafe fn PyDateTime_TimeZone_UTC() -> *mut PyObject { |
483 | (*PyDateTimeAPI()).TimeZone_UTC |
484 | } |
485 | |
486 | /// Populates the `PyDateTimeAPI` object |
487 | pub 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. |
513 | pub 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`. |
519 | pub 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. |
525 | pub 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`. |
531 | pub 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. |
537 | pub 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`. |
543 | pub 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. |
549 | pub 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`. |
555 | pub 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. |
561 | pub 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`. |
567 | pub 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 | |
578 | pub unsafe fn PyTimeZone_FromOffset(offset: *mut PyObject) -> *mut PyObject { |
579 | ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, std::ptr::null_mut()) |
580 | } |
581 | |
582 | pub 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))] |
590 | pub 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))] |
596 | pub 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)] |
602 | extern "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)] |
610 | extern "C" { |
611 | #[link_name = "_PyPyDateTime_Import" ] |
612 | pub fn PyDateTime_Import() -> *mut PyDateTime_CAPI; |
613 | } |
614 | |
615 | // Rust specific implementation details |
616 | |
617 | struct PyDateTimeAPISingleton(UnsafeCell<*mut PyDateTime_CAPI>); |
618 | unsafe impl Sync for PyDateTimeAPISingleton {} |
619 | |
620 | static PyDateTimeAPI_impl: PyDateTimeAPISingleton = |
621 | PyDateTimeAPISingleton(UnsafeCell::new(ptr::null_mut())); |
622 | |