1 /**
2   mirror datetime.h
3   */
4 module deimos.python.datetime;
5 
6 version(Python_3_1_Or_Later) {
7     version = PyCapsule;
8 }else version(Python_3_0_Or_Later) {
9     version = PyCObject;
10 }else version(Python_2_7_Or_Later) {
11     version = PyCapsule;
12 }else {
13     version = PyCObject;
14 }
15 
16 import deimos.python.object;
17 import deimos.python.pyport;
18 version(PyCapsule) {
19     import deimos.python.pycapsule;
20 }else version(PyCObject) {
21     import deimos.python.cobject;
22 }else static assert(0);
23 
24 
25 extern(C):
26 // Python-header-file: Include/datetime.h:
27 
28 /** # of bytes for year, month, and day. */
29 enum _PyDateTime_DATE_DATASIZE = 4;
30 /** # of bytes for hour, minute, second, and usecond. */
31 enum _PyDateTime_TIME_DATASIZE = 6;
32 /** # of bytes for year, month, day, hour, minute, second, and usecond. */
33 enum _PyDateTime_DATETIME_DATASIZE = 10;
34 
35 /// subclass of PyObject.
36 struct PyDateTime_Delta {
37     mixin PyObject_HEAD;
38 
39     /** -1 when unknown */
40     Py_hash_t hashcode;
41     /** -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
42     int days;
43     /** 0 <= seconds < 24*3600 is invariant */
44     int seconds;
45     /** 0 <= microseconds < 1000000 is invariant */
46     int microseconds;
47 }
48 /** a pure abstract base clase */
49 struct PyDateTime_TZInfo {
50     mixin PyObject_HEAD;
51 }
52 
53 /** The datetime and time types have hashcodes, and an optional tzinfo member,
54  * present if and only if hastzinfo is true.
55  */
56 template _PyTZINFO_HEAD() {
57     mixin PyObject_HEAD;
58     /// _
59     Py_hash_t hashcode;
60     /// _
61     ubyte hastzinfo;
62 }
63 
64 /** No _PyDateTime_BaseTZInfo is allocated; it's just to have something
65  * convenient to cast to, when getting at the hastzinfo member of objects
66  * starting with _PyTZINFO_HEAD.
67  */
68 struct _PyDateTime_BaseTZInfo {
69     mixin _PyTZINFO_HEAD;
70 }
71 
72 /** All time objects are of PyDateTime_TimeType, but that can be allocated
73  * in two ways, with or without a tzinfo member.  Without is the same as
74  * tzinfo == None, but consumes less memory.  _PyDateTime_BaseTime is an
75  * internal struct used to allocate the right amount of space for the
76  * "without" case.
77  */
78 template _PyDateTime_TIMEHEAD() {
79     mixin _PyTZINFO_HEAD;
80     /// _
81     ubyte[_PyDateTime_TIME_DATASIZE] data;
82 }
83 
84 /// _
85 struct _PyDateTime_BaseTime {
86     mixin _PyDateTime_TIMEHEAD;
87 }
88 
89 /// _
90 struct PyDateTime_Time {
91     mixin _PyDateTime_TIMEHEAD;
92     version(Python_3_6_Or_Later) {
93         ubyte fold;
94     }
95     PyObject* tzinfo;
96 }
97 
98 /** All datetime objects are of PyDateTime_DateTimeType, but that can be
99  * allocated in two ways too, just like for time objects above.  In addition,
100  * the plain date type is a base class for datetime, so it must also have
101  * a hastzinfo member (although it's unused there).
102  */
103 struct PyDateTime_Date {
104     mixin _PyTZINFO_HEAD;
105     /// _
106     ubyte[_PyDateTime_DATE_DATASIZE] data;
107 }
108 
109 /// _
110 template _PyDateTime_DATETIMEHEAD() {
111     mixin _PyTZINFO_HEAD;
112     ubyte[_PyDateTime_DATETIME_DATASIZE] data;
113 }
114 
115 /// _
116 struct _PyDateTime_BaseDateTime {
117     mixin _PyDateTime_DATETIMEHEAD;
118 }
119 
120 /// _
121 struct PyDateTime_DateTime {
122     mixin _PyDateTime_DATETIMEHEAD;
123     version(Python_3_6_Or_Later) {
124         ubyte fold;
125     }
126     PyObject* tzinfo;
127 }
128 
129 // D translations of C macros:
130 /** Applies for date and datetime instances. */
131 int PyDateTime_GET_YEAR()(PyObject* o) {
132     PyDateTime_Date* ot = cast(PyDateTime_Date*) o;
133     return (ot.data[0] << 8) | ot.data[1];
134 }
135 /** Applies for date and datetime instances. */
136 int PyDateTime_GET_MONTH()(PyObject* o) {
137     PyDateTime_Date* ot = cast(PyDateTime_Date*) o;
138     return ot.data[2];
139 }
140 /** Applies for date and datetime instances. */
141 int PyDateTime_GET_DAY()(PyObject* o) {
142     PyDateTime_Date* ot = cast(PyDateTime_Date*) o;
143     return ot.data[3];
144 }
145 
146 /** Applies for date and datetime instances. */
147 int PyDateTime_DATE_GET_HOUR()(PyObject* o) {
148     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
149     return ot.data[4];
150 }
151 /** Applies for date and datetime instances. */
152 int PyDateTime_DATE_GET_MINUTE()(PyObject* o) {
153     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
154     return ot.data[5];
155 }
156 /** Applies for date and datetime instances. */
157 int PyDateTime_DATE_GET_SECOND()(PyObject* o) {
158     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
159     return ot.data[6];
160 }
161 /** Applies for date and datetime instances. */
162 int PyDateTime_DATE_GET_MICROSECOND()(PyObject* o) {
163     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
164     return (ot.data[7] << 16) | (ot.data[8] << 8) | ot.data[9];
165 }
166 
167 version(Python_3_6_Or_Later) {
168     /// _
169     int PyDateTime_DATE_GET_FOLD()(PyObject* o) {
170         auto ot = cast(PyDateTime_DateTime*)o;
171         return ot.fold;
172     }
173 }
174 
175 /** Applies for time instances. */
176 int PyDateTime_TIME_GET_HOUR()(PyObject* o) {
177     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
178     return ot.data[0];
179 }
180 /** Applies for time instances. */
181 int PyDateTime_TIME_GET_MINUTE()(PyObject* o) {
182     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
183     return ot.data[1];
184 }
185 /** Applies for time instances. */
186 int PyDateTime_TIME_GET_SECOND()(PyObject* o) {
187     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
188     return ot.data[2];
189 }
190 /** Applies for time instances. */
191 int PyDateTime_TIME_GET_MICROSECOND()(PyObject* o) {
192     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
193     return (ot.data[3] << 16) | (ot.data[4] << 8) | ot.data[5];
194 }
195 
196 version(Python_3_6_Or_Later) {
197     /// _
198     int PyDateTime_TIME_GET_FOLD()(PyObject* o) {
199         auto ot = cast(PyDateTime_Time*) o;
200         return ot.fold;
201     }
202 }
203 
204 /** Structure for C API. */
205 struct PyDateTime_CAPI {
206     /** type objects */
207     PyTypeObject* DateType;
208     /// ditto
209     PyTypeObject* DateTimeType;
210     /// ditto
211     PyTypeObject* TimeType;
212     /// ditto
213     PyTypeObject* DeltaType;
214     /// ditto
215     PyTypeObject* TZInfoType;
216 
217     version(Python_3_7_Or_Later) {
218         PyObject* TimeZone_UTC;
219     }
220 
221     /** constructors */
222     PyObject* function(int, int, int, PyTypeObject*) Date_FromDate;
223     /// ditto
224     PyObject* function(int, int, int, int, int, int, int,
225             PyObject*, PyTypeObject*)
226         DateTime_FromDateAndTime;
227     /// ditto
228     PyObject* function(int, int, int, int, PyObject*, PyTypeObject*)
229         Time_FromTime;
230     /// ditto
231     PyObject* function(int, int, int, int, PyTypeObject*) Delta_FromDelta;
232     /// ditto
233     version(Python_3_7_Or_Later) {
234         PyObject* function(PyObject *offset, PyObject *name) TimeZone_FromTimeZone;
235     }
236 
237     /** constructors for the DB API */
238     PyObject* function(PyObject*, PyObject*, PyObject*) DateTime_FromTimestamp;
239     /// ditto
240     PyObject* function(PyObject*, PyObject*) Date_FromTimestamp;
241 
242     version(Python_3_6_Or_Later) {
243         PyObject* function(int, int, int, int, int, int, int, PyObject*, int, PyTypeObject*)
244             DateTime_FromDateAndTimeAndFold;
245 
246         PyObject* function(int, int, int, int, PyObject*, int, PyTypeObject*)
247             Time_FromTimeAndFold;
248     }
249 }
250 
251 // went away in python 3. who cares?
252 enum DATETIME_API_MAGIC = 0x414548d5;
253 
254 version(PyCapsule) {
255     enum PyDateTime_CAPSULE_NAME = "datetime.datetime_CAPI";
256 }
257 
258 /// _
259 static PyDateTime_CAPI* PyDateTimeAPI;
260 PyDateTime_CAPI* PyDateTime_IMPORT()() {
261     if (PyDateTimeAPI == null) {
262         version(PyCapsule) {
263             PyDateTimeAPI = cast(PyDateTime_CAPI*)
264                 PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0);
265         }else {
266             PyDateTimeAPI = cast(PyDateTime_CAPI*)
267                 PyCObject_Import("datetime", "datetime_CAPI");
268         }
269     }
270     return PyDateTimeAPI;
271 }
272 
273 // D translations of C macros:
274 version(Python_3_7_Or_Later) {
275     /// _
276     PyObject* PyDateTime_TimeZone_UTC()() {
277         return PyDateTimeAPI.TimeZone_UTC;
278     }
279 }
280 /// _
281 int PyDate_Check()(PyObject* op) {
282     return PyObject_TypeCheck(op, PyDateTimeAPI.DateType);
283 }
284 /// _
285 int PyDate_CheckExact()(PyObject* op) {
286     return Py_TYPE(op) == PyDateTimeAPI.DateType;
287 }
288 /// _
289 int PyDateTime_Check()(PyObject* op) {
290     return PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType);
291 }
292 /// _
293 int PyDateTime_CheckExact()(PyObject* op) {
294     return Py_TYPE(op) == PyDateTimeAPI.DateTimeType;
295 }
296 /// _
297 int PyTime_Check()(PyObject* op) {
298     return PyObject_TypeCheck(op, PyDateTimeAPI.TimeType);
299 }
300 /// _
301 int PyTime_CheckExact()(PyObject* op) {
302     return Py_TYPE(op) == PyDateTimeAPI.TimeType;
303 }
304 /// _
305 int PyDelta_Check()(PyObject* op) {
306     return PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType);
307 }
308 /// _
309 int PyDelta_CheckExact()(PyObject* op) {
310     return Py_TYPE(op) == PyDateTimeAPI.DeltaType;
311 }
312 /// _
313 int PyTZInfo_Check()(PyObject* op) {
314     return PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType);
315 }
316 /// _
317 int PyTZInfo_CheckExact()(PyObject* op) {
318     return Py_TYPE(op) == PyDateTimeAPI.TZInfoType;
319 }
320 
321 /// _
322 PyObject* PyDate_FromDate()(int year, int month, int day) {
323     return PyDateTimeAPI.Date_FromDate(year, month, day, PyDateTimeAPI.DateType);
324 }
325 /// _
326 PyObject* PyDateTime_FromDateAndTime()(
327         int year, int month, int day, int hour, int min, int sec, int usec) {
328     return PyDateTimeAPI.DateTime_FromDateAndTime(
329             year, month, day, hour, min, sec, usec,
330             cast(PyObject*) Py_None(), PyDateTimeAPI.DateTimeType);
331 }
332 
333 version(Python_3_6_Or_Later) {
334     /// _
335     PyObject* PyDateTime_FromDateAndTimeAndFold()(
336             int year, int month, int day, int hour, int min, int sec,
337             int usec, int fold) {
338         return PyDateTimeAPI.DateTime_FromDateAndTimeAndFold(
339                 year, month, day, hour,
340                 min, sec, usec, cast(PyObject*) Py_None(), fold,
341                 PyDateTimeAPI.DateTimeType);
342     }
343 }
344 
345 /// _
346 PyObject* PyTime_FromTime()(int hour, int minute, int second, int usecond) {
347     return PyDateTimeAPI.Time_FromTime(hour, minute, second, usecond,
348             cast(PyObject*) Py_None(), PyDateTimeAPI.TimeType);
349 }
350 
351 version(Python_3_6_Or_Later) {
352     /// _
353     PyObject* PyTime_FromTimeAndFold()(
354             int hour, int minute, int second, int usecond, int fold) {
355         return PyDateTimeAPI.Time_FromTimeAndFold(hour, minute, second, usecond,
356                 cast(PyObject*) Py_None(), fold, PyDateTimeAPI.TimeType);
357     }
358 }
359 /// _
360 PyObject* PyDelta_FromDSU()(int days, int seconds, int useconds) {
361     return PyDateTimeAPI.Delta_FromDelta(days, seconds, useconds, 1,
362             PyDateTimeAPI.DeltaType);
363 }
364 version(Python_3_7_Or_Later) {
365     /// _
366     PyObject* PyTimeZone_FromOffset()(PyObject* offset) { 
367         return PyDateTimeAPI.TimeZone_FromTimeZone(offset, null);
368     }
369 
370     /// _
371     PyObject* PyTimeZone_FromOffsetAndName()(PyObject* offset, PyObject* name) { 
372         return PyDateTimeAPI.TimeZone_FromTimeZone(offset, name);
373     }
374 }
375 /// _
376 PyObject* PyDateTime_FromTimestamp()(PyObject* args) {
377     return PyDateTimeAPI.DateTime_FromTimestamp(
378             cast(PyObject*) (PyDateTimeAPI.DateTimeType), args, null);
379 }
380 /// _
381 PyObject* PyDate_FromTimestamp()(PyObject* args) {
382     return PyDateTimeAPI.Date_FromTimestamp(
383             cast(PyObject*) (PyDateTimeAPI.DateType), args);
384 }