this repo has no description
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