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     /** constructors */
218     PyObject* function(int, int, int, PyTypeObject*) Date_FromDate;
219     /// ditto
220     PyObject* function(int, int, int, int, int, int, int,
221             PyObject*, PyTypeObject*) 
222         DateTime_FromDateAndTime;
223     /// ditto
224     PyObject* function(int, int, int, int, PyObject*, PyTypeObject*) 
225         Time_FromTime;
226     /// ditto
227     PyObject* function(int, int, int, int, PyTypeObject*) Delta_FromDelta;
228 
229     /** constructors for the DB API */
230     PyObject* function(PyObject*, PyObject*, PyObject*) DateTime_FromTimestamp;
231     /// ditto
232     PyObject* function(PyObject*, PyObject*) Date_FromTimestamp;
233 
234     version(Python_3_6_Or_Later) {
235         PyObject* function(int, int, int, int, int, int, int, PyObject*, int, PyTypeObject*) 
236             DateTime_FromDateAndTimeAndFold;
237 
238         PyObject* function(int, int, int, int, PyObject*, int, PyTypeObject*) 
239             Time_FromTimeAndFold;
240     }
241 }
242 
243 // went away in python 3. who cares?
244 enum DATETIME_API_MAGIC = 0x414548d5;
245 
246 version(PyCapsule) {
247     enum PyDateTime_CAPSULE_NAME = "datetime.datetime_CAPI";
248 }
249 
250 /// _
251 static PyDateTime_CAPI* PyDateTimeAPI;
252 PyDateTime_CAPI* PyDateTime_IMPORT()() {
253     if (PyDateTimeAPI == null) {
254         version(PyCapsule) {
255             PyDateTimeAPI = cast(PyDateTime_CAPI*)
256                 PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0);
257         }else {
258             PyDateTimeAPI = cast(PyDateTime_CAPI*)
259                 PyCObject_Import("datetime", "datetime_CAPI");
260         }
261     }
262     return PyDateTimeAPI;
263 }
264 
265 // D translations of C macros:
266 /// _
267 int PyDate_Check()(PyObject* op) {
268     return PyObject_TypeCheck(op, PyDateTimeAPI.DateType);
269 }
270 /// _
271 int PyDate_CheckExact()(PyObject* op) {
272     return Py_TYPE(op) == PyDateTimeAPI.DateType;
273 }
274 /// _
275 int PyDateTime_Check()(PyObject* op) {
276     return PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType);
277 }
278 /// _
279 int PyDateTime_CheckExact()(PyObject* op) {
280     return Py_TYPE(op) == PyDateTimeAPI.DateTimeType;
281 }
282 /// _
283 int PyTime_Check()(PyObject* op) {
284     return PyObject_TypeCheck(op, PyDateTimeAPI.TimeType);
285 }
286 /// _
287 int PyTime_CheckExact()(PyObject* op) {
288     return Py_TYPE(op) == PyDateTimeAPI.TimeType;
289 }
290 /// _
291 int PyDelta_Check()(PyObject* op) {
292     return PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType);
293 }
294 /// _
295 int PyDelta_CheckExact()(PyObject* op) {
296     return Py_TYPE(op) == PyDateTimeAPI.DeltaType;
297 }
298 /// _
299 int PyTZInfo_Check()(PyObject* op) {
300     return PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType);
301 }
302 /// _
303 int PyTZInfo_CheckExact()(PyObject* op) {
304     return Py_TYPE(op) == PyDateTimeAPI.TZInfoType;
305 }
306 
307 /// _
308 PyObject* PyDate_FromDate()(int year, int month, int day) {
309     return PyDateTimeAPI.Date_FromDate(year, month, day, PyDateTimeAPI.DateType);
310 }
311 /// _
312 PyObject* PyDateTime_FromDateAndTime()(
313         int year, int month, int day, int hour, int min, int sec, int usec) {
314     return PyDateTimeAPI.DateTime_FromDateAndTime(
315             year, month, day, hour, min, sec, usec, 
316             cast(PyObject*) Py_None(), PyDateTimeAPI.DateTimeType);
317 }
318 
319 version(Python_3_6_Or_Later) {
320     /// _
321     PyObject* PyDateTime_FromDateAndTimeAndFold()(
322             int year, int month, int day, int hour, int min, int sec, 
323             int usec, int fold) {
324         return PyDateTimeAPI.DateTime_FromDateAndTimeAndFold(
325                 year, month, day, hour,
326                 min, sec, usec, cast(PyObject*) Py_None(), fold, 
327                 PyDateTimeAPI.DateTimeType);
328     }
329 }
330 
331 /// _
332 PyObject* PyTime_FromTime()(int hour, int minute, int second, int usecond) {
333     return PyDateTimeAPI.Time_FromTime(hour, minute, second, usecond,
334             cast(PyObject*) Py_None(), PyDateTimeAPI.TimeType);
335 }
336 
337 version(Python_3_6_Or_Later) {
338     /// _
339     PyObject* PyTime_FromTimeAndFold()(
340             int hour, int minute, int second, int usecond, int fold) {
341         return PyDateTimeAPI.Time_FromTimeAndFold(hour, minute, second, usecond,
342                 cast(PyObject*) Py_None(), fold, PyDateTimeAPI.TimeType);
343     }
344 }
345 /// _
346 PyObject* PyDelta_FromDSU()(int days, int seconds, int useconds) {
347     return PyDateTimeAPI.Delta_FromDelta(days, seconds, useconds, 1,
348             PyDateTimeAPI.DeltaType);
349 }
350 /// _
351 PyObject* PyDateTime_FromTimestamp()(PyObject* args) {
352     return PyDateTimeAPI.DateTime_FromTimestamp(
353             cast(PyObject*) (PyDateTimeAPI.DateTimeType), args, null);
354 }
355 /// _
356 PyObject* PyDate_FromTimestamp()(PyObject* args) {
357     return PyDateTimeAPI.Date_FromTimestamp(
358             cast(PyObject*) (PyDateTimeAPI.DateType), args);
359 }
360 
361