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 }