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     PyObject* tzinfo;
93 }
94 
95 /** All datetime objects are of PyDateTime_DateTimeType, but that can be
96  * allocated in two ways too, just like for time objects above.  In addition,
97  * the plain date type is a base class for datetime, so it must also have
98  * a hastzinfo member (although it's unused there).
99  */
100 struct PyDateTime_Date {
101     mixin _PyTZINFO_HEAD;
102     /// _
103     ubyte[_PyDateTime_DATE_DATASIZE] data;
104 }
105 
106 /// _
107 template _PyDateTime_DATETIMEHEAD() {
108     mixin _PyTZINFO_HEAD;
109     ubyte[_PyDateTime_DATETIME_DATASIZE] data;
110 }
111 
112 /// _
113 struct _PyDateTime_BaseDateTime {
114     mixin _PyDateTime_DATETIMEHEAD;
115 }
116 
117 /// _
118 struct PyDateTime_DateTime {
119     mixin _PyDateTime_DATETIMEHEAD;
120     PyObject* tzinfo;
121 }
122 
123 // D translations of C macros:
124 /** Applies for date and datetime instances. */
125 int PyDateTime_GET_YEAR()(PyObject* o) {
126     PyDateTime_Date* ot = cast(PyDateTime_Date*) o;
127     return (ot.data[0] << 8) | ot.data[1];
128 }
129 /** Applies for date and datetime instances. */
130 int PyDateTime_GET_MONTH()(PyObject* o) {
131     PyDateTime_Date* ot = cast(PyDateTime_Date*) o;
132     return ot.data[2];
133 }
134 /** Applies for date and datetime instances. */
135 int PyDateTime_GET_DAY()(PyObject* o) {
136     PyDateTime_Date* ot = cast(PyDateTime_Date*) o;
137     return ot.data[3];
138 }
139 
140 /** Applies for date and datetime instances. */
141 int PyDateTime_DATE_GET_HOUR()(PyObject* o) {
142     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
143     return ot.data[4];
144 }
145 /** Applies for date and datetime instances. */
146 int PyDateTime_DATE_GET_MINUTE()(PyObject* o) {
147     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
148     return ot.data[5];
149 }
150 /** Applies for date and datetime instances. */
151 int PyDateTime_DATE_GET_SECOND()(PyObject* o) {
152     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
153     return ot.data[6];
154 }
155 /** Applies for date and datetime instances. */
156 int PyDateTime_DATE_GET_MICROSECOND()(PyObject* o) {
157     PyDateTime_DateTime* ot = cast(PyDateTime_DateTime*) o;
158     return (ot.data[7] << 16) | (ot.data[8] << 8) | ot.data[9];
159 }
160 
161 /** Applies for time instances. */
162 int PyDateTime_TIME_GET_HOUR()(PyObject* o) {
163     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
164     return ot.data[0];
165 }
166 /** Applies for time instances. */
167 int PyDateTime_TIME_GET_MINUTE()(PyObject* o) {
168     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
169     return ot.data[1];
170 }
171 /** Applies for time instances. */
172 int PyDateTime_TIME_GET_SECOND()(PyObject* o) {
173     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
174     return ot.data[2];
175 }
176 /** Applies for time instances. */
177 int PyDateTime_TIME_GET_MICROSECOND()(PyObject* o) {
178     PyDateTime_Time* ot = cast(PyDateTime_Time*) o;
179     return (ot.data[3] << 16) | (ot.data[4] << 8) | ot.data[5];
180 }
181 
182 /** Structure for C API. */
183 struct PyDateTime_CAPI {
184     /** type objects */
185     PyTypeObject* DateType;
186     /// ditto
187     PyTypeObject* DateTimeType;
188     /// ditto
189     PyTypeObject* TimeType;
190     /// ditto
191     PyTypeObject* DeltaType;
192     /// ditto
193     PyTypeObject* TZInfoType;
194 
195     /** constructors */
196     PyObject* function(int, int, int, PyTypeObject*) Date_FromDate;
197     /// ditto
198     PyObject* function(int, int, int, int, int, int, int,
199             PyObject*, PyTypeObject*) DateTime_FromDateAndTime;
200     /// ditto
201     PyObject* function(int, int, int, int, PyObject*, PyTypeObject*) Time_FromTime;
202     /// ditto
203     PyObject* function(int, int, int, int, PyTypeObject*) Delta_FromDelta;
204 
205     /** constructors for the DB API */
206     PyObject* function(PyObject*, PyObject*, PyObject*) DateTime_FromTimestamp;
207     /// ditto
208     PyObject* function(PyObject*, PyObject*) Date_FromTimestamp;
209 }
210 
211 // went away in python 3. who cares?
212 enum DATETIME_API_MAGIC = 0x414548d5;
213 
214 version(PyCapsule) {
215     enum PyDateTime_CAPSULE_NAME = "datetime.datetime_CAPI";
216 }
217 
218 /// _
219 static PyDateTime_CAPI* PyDateTimeAPI;
220 PyDateTime_CAPI* PyDateTime_IMPORT()() {
221     if (PyDateTimeAPI == null) {
222         version(PyCapsule) {
223             PyDateTimeAPI = cast(PyDateTime_CAPI*)
224                 PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0);
225         }else {
226             PyDateTimeAPI = cast(PyDateTime_CAPI*)
227                 PyCObject_Import("datetime", "datetime_CAPI");
228         }
229     }
230     return PyDateTimeAPI;
231 }
232 
233 // D translations of C macros:
234 /// _
235 int PyDate_Check()(PyObject* op) {
236     return PyObject_TypeCheck(op, PyDateTimeAPI.DateType);
237 }
238 /// _
239 int PyDate_CheckExact()(PyObject* op) {
240     return Py_TYPE(op) == PyDateTimeAPI.DateType;
241 }
242 /// _
243 int PyDateTime_Check()(PyObject* op) {
244     return PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType);
245 }
246 /// _
247 int PyDateTime_CheckExact()(PyObject* op) {
248     return Py_TYPE(op) == PyDateTimeAPI.DateTimeType;
249 }
250 /// _
251 int PyTime_Check()(PyObject* op) {
252     return PyObject_TypeCheck(op, PyDateTimeAPI.TimeType);
253 }
254 /// _
255 int PyTime_CheckExact()(PyObject* op) {
256     return Py_TYPE(op) == PyDateTimeAPI.TimeType;
257 }
258 /// _
259 int PyDelta_Check()(PyObject* op) {
260     return PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType);
261 }
262 /// _
263 int PyDelta_CheckExact()(PyObject* op) {
264     return Py_TYPE(op) == PyDateTimeAPI.DeltaType;
265 }
266 /// _
267 int PyTZInfo_Check()(PyObject* op) {
268     return PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType);
269 }
270 /// _
271 int PyTZInfo_CheckExact()(PyObject* op) {
272     return Py_TYPE(op) == PyDateTimeAPI.TZInfoType;
273 }
274 
275 /// _
276 PyObject* PyDate_FromDate()(int year, int month, int day) {
277     return PyDateTimeAPI.Date_FromDate(year, month, day, PyDateTimeAPI.DateType);
278 }
279 /// _
280 PyObject* PyDateTime_FromDateAndTime()(int year, int month, int day, int hour, int min, int sec, int usec) {
281     return PyDateTimeAPI.DateTime_FromDateAndTime(year, month, day, hour,
282             min, sec, usec, cast(PyObject*) Py_None(), PyDateTimeAPI.DateTimeType);
283 }
284 /// _
285 PyObject* PyTime_FromTime()(int hour, int minute, int second, int usecond) {
286     return PyDateTimeAPI.Time_FromTime(hour, minute, second, usecond,
287             cast(PyObject*) Py_None(), PyDateTimeAPI.TimeType);
288 }
289 /// _
290 PyObject* PyDelta_FromDSU()(int days, int seconds, int useconds) {
291     return PyDateTimeAPI.Delta_FromDelta(days, seconds, useconds, 1,
292             PyDateTimeAPI.DeltaType);
293 }
294 /// _
295 PyObject* PyDateTime_FromTimestamp()(PyObject* args) {
296     return PyDateTimeAPI.DateTime_FromTimestamp(
297             cast(PyObject*) (PyDateTimeAPI.DateTimeType), args, null);
298 }
299 /// _
300 PyObject* PyDate_FromTimestamp()(PyObject* args) {
301     return PyDateTimeAPI.Date_FromTimestamp(
302             cast(PyObject*) (PyDateTimeAPI.DateType), args);
303 }
304 
305