this repo has no description
at trunk 271 lines 11 kB view raw
1/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */ 2#pragma once 3 4#include "Python.h" 5 6#ifdef __cplusplus 7extern "C" { 8#endif 9 10// Fields are packed into successive bytes, each viewed as unsigned and 11// big-endian, unless otherwise noted: 12// 13// byte offset 14// 0 year 2 bytes, 1-9999 15// 2 month 1 byte, 1-12 16// 3 day 1 byte, 1-31 17// 4 hour 1 byte, 0-23 18// 5 minute 1 byte, 0-59 19// 6 second 1 byte, 0-59 20// 7 usecond 3 bytes, 0-999999 21// 10 22 23// # of bytes for year, month, and day. 24#define _PyDateTime_DATE_DATASIZE 4 25 26// # of bytes for hour, minute, second, and usecond. 27#define _PyDateTime_TIME_DATASIZE 6 28 29// # of bytes for year, month, day, hour, minute, second, and usecond. 30#define _PyDateTime_DATETIME_DATASIZE 10 31 32typedef struct { 33 PyObject_HEAD 34 Py_hash_t hashcode; // -1 when unknown 35 int days; // -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS 36 int seconds; // 0 <= seconds < 24*3600 is invariant 37 int microseconds; // 0 <= microseconds < 1000000 is invariant 38} PyDateTime_Delta; 39 40typedef struct { 41 PyObject_HEAD // a pure abstract base class 42} PyDateTime_TZInfo; 43 44// The datetime and time types have hashcodes, and an optional tzinfo member, 45// present if and only if hastzinfo is true. 46#define _PyTZINFO_HEAD \ 47 PyObject_HEAD \ 48 Py_hash_t hashcode; \ 49 char hastzinfo; // boolean flag 50 51// No _PyDateTime_BaseTZInfo is allocated; it's just to have something 52// convenient to cast to, when getting at the hastzinfo member of objects 53// starting with _PyTZINFO_HEAD. 54typedef struct { 55 _PyTZINFO_HEAD 56} _PyDateTime_BaseTZInfo; 57 58// All time objects are of PyDateTime_TimeType, but that can be allocated 59// in two ways, with or without a tzinfo member. Without is the same as 60// tzinfo == None, but consumes less memory. _PyDateTime_BaseTime is an 61// internal struct used to allocate the right amount of space for the 62// "without" case. 63#define _PyDateTime_TIMEHEAD \ 64 _PyTZINFO_HEAD unsigned char data[_PyDateTime_TIME_DATASIZE]; 65 66typedef struct { 67 _PyDateTime_TIMEHEAD 68} _PyDateTime_BaseTime; // hastzinfo false 69 70typedef struct { 71 _PyDateTime_TIMEHEAD unsigned char fold; 72 PyObject* tzinfo; 73} PyDateTime_Time; // hastzinfo true 74 75// All datetime objects are of PyDateTime_DateTimeType, but that can be 76// allocated in two ways too, just like for time objects above. In addition, 77// the plain date type is a base class for datetime, so it must also have 78// a hastzinfo member (although it's unused there). 79typedef struct { 80 _PyTZINFO_HEAD unsigned char data[_PyDateTime_DATE_DATASIZE]; 81} PyDateTime_Date; 82 83#define _PyDateTime_DATETIMEHEAD \ 84 _PyTZINFO_HEAD unsigned char data[_PyDateTime_DATETIME_DATASIZE]; 85 86typedef struct { 87 _PyDateTime_DATETIMEHEAD 88} _PyDateTime_BaseDateTime; // hastzinfo false 89 90typedef struct { 91 _PyDateTime_DATETIMEHEAD unsigned char fold; 92 PyObject* tzinfo; 93} PyDateTime_DateTime; // hastzinfo true 94 95// Apply for date and datetime instances. 96#define PyDateTime_GET_YEAR(o) \ 97 ((((PyDateTime_Date*)o)->data[0] << 8) | ((PyDateTime_Date*)o)->data[1]) 98#define PyDateTime_GET_MONTH(o) (((PyDateTime_Date*)o)->data[2]) 99#define PyDateTime_GET_DAY(o) (((PyDateTime_Date*)o)->data[3]) 100 101#define PyDateTime_DATE_GET_HOUR(o) (((PyDateTime_DateTime*)o)->data[4]) 102#define PyDateTime_DATE_GET_MINUTE(o) (((PyDateTime_DateTime*)o)->data[5]) 103#define PyDateTime_DATE_GET_SECOND(o) (((PyDateTime_DateTime*)o)->data[6]) 104#define PyDateTime_DATE_GET_MICROSECOND(o) \ 105 ((((PyDateTime_DateTime*)o)->data[7] << 16) | \ 106 (((PyDateTime_DateTime*)o)->data[8] << 8) | \ 107 ((PyDateTime_DateTime*)o)->data[9]) 108#define PyDateTime_DATE_GET_FOLD(o) (((PyDateTime_DateTime*)o)->fold) 109 110// Apply for time instances. 111#define PyDateTime_TIME_GET_HOUR(o) (((PyDateTime_Time*)o)->data[0]) 112#define PyDateTime_TIME_GET_MINUTE(o) (((PyDateTime_Time*)o)->data[1]) 113#define PyDateTime_TIME_GET_SECOND(o) (((PyDateTime_Time*)o)->data[2]) 114#define PyDateTime_TIME_GET_MICROSECOND(o) \ 115 ((((PyDateTime_Time*)o)->data[3] << 16) | \ 116 (((PyDateTime_Time*)o)->data[4] << 8) | ((PyDateTime_Time*)o)->data[5]) 117#define PyDateTime_TIME_GET_FOLD(o) (((PyDateTime_Time*)o)->fold) 118 119// Apply for time delta instances 120#define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days) 121#define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds) 122#define PyDateTime_DELTA_GET_MICROSECONDS(o) \ 123 (((PyDateTime_Delta*)o)->microseconds) 124 125// Define structure for C API. 126typedef struct { 127 // type objects 128 PyTypeObject* DateType; 129 PyTypeObject* DateTimeType; 130 PyTypeObject* TimeType; 131 PyTypeObject* DeltaType; 132 PyTypeObject* TZInfoType; 133 134 // singletons 135 PyObject* TimeZone_UTC; 136 137 // constructors 138 PyObject* (*Date_FromDate)(int, int, int, PyTypeObject*); 139 PyObject* (*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, 140 PyObject*, PyTypeObject*); 141 PyObject* (*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*); 142 PyObject* (*Delta_FromDelta)(int, int, int, int, PyTypeObject*); 143 PyObject* (*TimeZone_FromTimeZone)(PyObject* offset, PyObject* name); 144 145 // constructors for the DB API 146 PyObject* (*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*); 147 PyObject* (*Date_FromTimestamp)(PyObject*, PyObject*); 148 149 // PEP 495 constructors 150 PyObject* (*DateTime_FromDateAndTimeAndFold)(int, int, int, int, int, int, 151 int, PyObject*, int, 152 PyTypeObject*); 153 PyObject* (*Time_FromTimeAndFold)(int, int, int, int, PyObject*, int, 154 PyTypeObject*); 155 156} PyDateTime_CAPI; 157 158#define PyDateTime_CAPSULE_NAME "datetime.datetime_CAPI" 159 160typedef struct { 161 PyTypeObject* TimeZoneType; 162 163 // The interned Epoch datetime instance 164 PyObject* Epoch; 165 166 // Conversion factors 167 PyObject* us_per_ms; // 1000 168 PyObject* us_per_second; // 1000000 169 PyObject* us_per_minute; // 1e6 * 60 170 PyObject* us_per_hour; // 1e6 * 3600 171 PyObject* us_per_day; // 1e6 * 3600 * 24 172 PyObject* us_per_week; // 1e6 * 3600 * 24 * 7 173 PyObject* seconds_per_day; // 3600 * 24 174 175 // Identifiers 176 PyObject* __getinitargs__; 177 PyObject* __getstate__; 178 PyObject* _strptime_datetime; 179 PyObject* as_integer_ratio; 180 PyObject* fromtimestamp; 181 PyObject* fromutc; 182 PyObject* isoformat; 183 PyObject* strftime; 184 PyObject* struct_time; 185 PyObject* time; 186 PyObject* timetuple; 187 PyObject* tzname; 188 189 // C API. Clients get at this via PyDateTime_IMPORT. 190 PyDateTime_CAPI CAPI; 191} datetime_state; 192 193extern struct PyModuleDef datetimemodule; 194 195#define datetime_state(o) ((datetime_state*)PyModule_GetState(o)) 196#define datetime_global(x) \ 197 (datetime_state(PyState_FindModule(&datetimemodule))->x) 198 199#define PyDateTime_IMPORT 200 201// Macro for access to the UTC singleton 202#define PyDateTime_TimeZone_UTC datetime_global(CAPI.TimeZone_UTC) 203 204// Macros for type checking when not building the Python core. 205#define PyDate_Check(op) PyObject_TypeCheck(op, datetime_global(CAPI.DateType)) 206#define PyDate_CheckExact(op) (Py_TYPE(op) == datetime_global(CAPI.DateType)) 207 208#define PyDateTime_Check(op) \ 209 PyObject_TypeCheck(op, datetime_global(CAPI.DateTimeType)) 210#define PyDateTime_CheckExact(op) \ 211 (Py_TYPE(op) == datetime_global(CAPI.DateTimeType)) 212 213#define PyTime_Check(op) PyObject_TypeCheck(op, datetime_global(CAPI.TimeType)) 214#define PyTime_CheckExact(op) (Py_TYPE(op) == datetime_global(CAPI.TimeType)) 215 216#define PyDelta_Check(op) \ 217 PyObject_TypeCheck(op, datetime_global(CAPI.DeltaType)) 218#define PyDelta_CheckExact(op) (Py_TYPE(op) == datetime_global(CAPI.DeltaType)) 219 220#define PyTZInfo_Check(op) \ 221 PyObject_TypeCheck(op, datetime_global(CAPI.TZInfoType)) 222#define PyTZInfo_CheckExact(op) \ 223 (Py_TYPE(op) == datetime_global(CAPI.TZInfoType)) 224 225// Macros for accessing constructors in a simplified fashion. 226#define PyDate_FromDate(year, month, day) \ 227 datetime_global(CAPI.Date_FromDate)(year, month, day, \ 228 datetime_global(CAPI.DateType)) 229 230#define PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, usec) \ 231 datetime_global(CAPI.DateTime_FromDateAndTime)( \ 232 year, month, day, hour, min, sec, usec, Py_None, \ 233 datetime_global(CAPI.DateTimeType)) 234 235#define PyDateTime_FromDateAndTimeAndFold(year, month, day, hour, min, sec, \ 236 usec, fold) \ 237 datetime_global(CAPI.DateTime_FromDateAndTimeAndFold)( \ 238 year, month, day, hour, min, sec, usec, Py_None, fold, \ 239 datetime_global(CAPI.DateTimeType)) 240 241#define PyTime_FromTime(hour, minute, second, usecond) \ 242 datetime_global(CAPI.Time_FromTime)(hour, minute, second, usecond, Py_None, \ 243 datetime_global(CAPI.TimeType)) 244 245#define PyTime_FromTimeAndFold(hour, minute, second, usecond, fold) \ 246 datetime_global(CAPI.Time_FromTimeAndFold)(hour, minute, second, usecond, \ 247 Py_None, fold, \ 248 datetime_global(CAPI.TimeType)) 249 250#define PyDelta_FromDSU(days, seconds, useconds) \ 251 datetime_global(CAPI.Delta_FromDelta)(days, seconds, useconds, 1, \ 252 datetime_global(CAPI.DeltaType)) 253 254#define PyTimeZone_FromOffset(offset) \ 255 datetime_global(CAPI.TimeZone_FromTimeZone)(offset, NULL) 256 257#define PyTimeZone_FromOffsetAndName(offset, name) \ 258 datetime_global(CAPI.TimeZone_FromTimeZone)(offset, name) 259 260// Macros supporting the DB API. 261#define PyDateTime_FromTimestamp(args) \ 262 datetime_global(CAPI.DateTime_FromTimestamp)( \ 263 (PyObject*)(datetime_global(CAPI.DateTimeType)), args, NULL) 264 265#define PyDate_FromTimestamp(args) \ 266 datetime_global(CAPI.Date_FromTimestamp)( \ 267 (PyObject*)(datetime_global(CAPI.DateType)), args) 268 269#ifdef __cplusplus 270} 271#endif