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