datetime.h 8.09 KB
Newer Older
1 2 3 4 5
/*  datetime.h
 */

#ifndef DATETIME_H
#define DATETIME_H
6 7 8
#ifdef __cplusplus
extern "C" {
#endif
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

/* Fields are packed into successive bytes, each viewed as unsigned and
 * big-endian, unless otherwise noted:
 *
 * byte offset
 *  0 		year     2 bytes, 1-9999
 *  2		month    1 byte, 1-12
 *  3 		day      1 byte, 1-31
 *  4		hour     1 byte, 0-23
 *  5 		minute   1 byte, 0-59
 *  6 		second   1 byte, 0-59
 *  7 		usecond  3 bytes, 0-999999
 * 10
 */

/* # of bytes for year, month, and day. */
#define _PyDateTime_DATE_DATASIZE 4

/* # of bytes for hour, minute, second, and usecond. */
#define _PyDateTime_TIME_DATASIZE 6

/* # of bytes for year, month, day, hour, minute, second, and usecond. */
#define _PyDateTime_DATETIME_DATASIZE 10

33

34 35 36
typedef struct
{
	PyObject_HEAD
37 38 39 40 41
	long hashcode;		/* -1 when unknown */
	int days;		/* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
	int seconds;		/* 0 <= seconds < 24*3600 is invariant */
	int microseconds;	/* 0 <= microseconds < 1000000 is invariant */
} PyDateTime_Delta;
42 43 44

typedef struct
{
45 46
	PyObject_HEAD		/* a pure abstract base clase */
} PyDateTime_TZInfo;
47

48

49 50 51 52 53 54 55
/* The datetime and time types have hashcodes, and an optional tzinfo member,
 * present if and only if hastzinfo is true.
 */
#define _PyTZINFO_HEAD		\
	PyObject_HEAD		\
	long hashcode;		\
	char hastzinfo;		/* boolean flag */
56

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/* No _PyDateTime_BaseTZInfo is allocated; it's just to have something
 * convenient to cast to, when getting at the hastzinfo member of objects
 * starting with _PyTZINFO_HEAD.
 */
typedef struct
{
	_PyTZINFO_HEAD
} _PyDateTime_BaseTZInfo;

/* All time objects are of PyDateTime_TimeType, but that can be allocated
 * in two ways, with or without a tzinfo member.  Without is the same as
 * tzinfo == None, but consumes less memory.  _PyDateTime_BaseTime is an
 * internal struct used to allocate the right amount of space for the
 * "without" case.
 */
72 73 74 75
#define _PyDateTime_TIMEHEAD	\
	_PyTZINFO_HEAD		\
	unsigned char data[_PyDateTime_TIME_DATASIZE];

76 77
typedef struct
{
78 79
	_PyDateTime_TIMEHEAD
} _PyDateTime_BaseTime;		/* hastzinfo false */
80 81 82

typedef struct
{
83
	_PyDateTime_TIMEHEAD
84
	PyObject *tzinfo;
85 86
} PyDateTime_Time;		/* hastzinfo true */

87

88 89 90 91 92
/* All datetime objects are of PyDateTime_DateTimeType, but that can be
 * allocated in two ways too, just like for time objects above.  In addition,
 * the plain date type is a base class for datetime, so it must also have
 * a hastzinfo member (although it's unused there).
 */
93 94
typedef struct
{
95 96 97 98 99 100
	_PyTZINFO_HEAD
	unsigned char data[_PyDateTime_DATE_DATASIZE];
} PyDateTime_Date;

#define _PyDateTime_DATETIMEHEAD	\
	_PyTZINFO_HEAD			\
101
	unsigned char data[_PyDateTime_DATETIME_DATASIZE];
102 103 104

typedef struct
{
105 106 107 108 109 110
	_PyDateTime_DATETIMEHEAD
} _PyDateTime_BaseDateTime;	/* hastzinfo false */

typedef struct
{
	_PyDateTime_DATETIMEHEAD
111
	PyObject *tzinfo;
112
} PyDateTime_DateTime;		/* hastzinfo true */
113

114

115
/* Apply for date and datetime instances. */
116 117 118 119 120 121 122 123 124 125 126 127 128
#define PyDateTime_GET_YEAR(o)     ((((PyDateTime_Date*)o)->data[0] << 8) | \
                                     ((PyDateTime_Date*)o)->data[1])
#define PyDateTime_GET_MONTH(o)    (((PyDateTime_Date*)o)->data[2])
#define PyDateTime_GET_DAY(o)      (((PyDateTime_Date*)o)->data[3])

#define PyDateTime_DATE_GET_HOUR(o)        (((PyDateTime_DateTime*)o)->data[4])
#define PyDateTime_DATE_GET_MINUTE(o)      (((PyDateTime_DateTime*)o)->data[5])
#define PyDateTime_DATE_GET_SECOND(o)      (((PyDateTime_DateTime*)o)->data[6])
#define PyDateTime_DATE_GET_MICROSECOND(o) 		\
	((((PyDateTime_DateTime*)o)->data[7] << 16) |	\
         (((PyDateTime_DateTime*)o)->data[8] << 8)  |	\
          ((PyDateTime_DateTime*)o)->data[9])

129
/* Apply for time instances. */
130 131 132 133 134 135 136 137
#define PyDateTime_TIME_GET_HOUR(o)        (((PyDateTime_Time*)o)->data[0])
#define PyDateTime_TIME_GET_MINUTE(o)      (((PyDateTime_Time*)o)->data[1])
#define PyDateTime_TIME_GET_SECOND(o)      (((PyDateTime_Time*)o)->data[2])
#define PyDateTime_TIME_GET_MICROSECOND(o) 		\
	((((PyDateTime_Time*)o)->data[3] << 16) |	\
         (((PyDateTime_Time*)o)->data[4] << 8)  |	\
          ((PyDateTime_Time*)o)->data[5])

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

/* Define structure for C API. */
typedef struct {
    /* type objects */
    PyTypeObject *DateType;
    PyTypeObject *DateTimeType;
    PyTypeObject *TimeType;
    PyTypeObject *DeltaType;
    PyTypeObject *TZInfoType;

    /* constructors */
    PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*);
    PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int,
            PyObject*, PyTypeObject*);
    PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*);
    PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*);

    /* constructors for the DB API */
    PyObject *(*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*);
    PyObject *(*Date_FromTimestamp)(PyObject*, PyObject*);

} PyDateTime_CAPI;


/* "magic" constant used to partially protect against developer mistakes. */
#define DATETIME_API_MAGIC 0x414548d5

#ifdef Py_BUILD_CORE

/* Macros for type checking when building the Python core. */
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
#define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType)
#define PyDate_CheckExact(op) ((op)->ob_type == &PyDateTime_DateType)

#define PyDateTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateTimeType)
#define PyDateTime_CheckExact(op) ((op)->ob_type == &PyDateTime_DateTimeType)

#define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType)
#define PyTime_CheckExact(op) ((op)->ob_type == &PyDateTime_TimeType)

#define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType)
#define PyDelta_CheckExact(op) ((op)->ob_type == &PyDateTime_DeltaType)

#define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType)
#define PyTZInfo_CheckExact(op) ((op)->ob_type == &PyDateTime_TZInfoType)

183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
#else

/* Define global variable for the C API and a macro for setting it. */
static PyDateTime_CAPI *PyDateTimeAPI;

#define PyDateTime_IMPORT \
        PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_Import("datetime", \
                                                            "datetime_CAPI")

/* This macro would be used if PyCObject_ImportEx() was created.
#define PyDateTime_IMPORT \
        PyDateTimeAPI = (PyDateTime_CAPI*) PyCObject_ImportEx("datetime", \
                                                            "datetime_CAPI", \
                                                            DATETIME_API_MAGIC)
*/

/* Macros for type checking when not building the Python core. */
#define PyDate_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateType)
#define PyDate_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->DateType)

#define PyDateTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DateTimeType)
#define PyDateTime_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->DateTimeType)

#define PyTime_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TimeType)
#define PyTime_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->TimeType)

#define PyDelta_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->DeltaType)
#define PyDelta_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->DeltaType)

#define PyTZInfo_Check(op) PyObject_TypeCheck(op, PyDateTimeAPI->TZInfoType)
#define PyTZInfo_CheckExact(op) ((op)->ob_type == PyDateTimeAPI->TZInfoType)

/* Macros for accessing constructors in a simplified fashion. */
#define PyDate_FromDate(year, month, day) \
	PyDateTimeAPI->Date_FromDate(year, month, day, PyDateTimeAPI->DateType)

#define PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, usec) \
	PyDateTimeAPI->DateTime_FromDateAndTime(year, month, day, hour, \
		min, sec, usec, Py_None, PyDateTimeAPI->DateTimeType)

#define PyTime_FromTime(hour, minute, second, usecond) \
	PyDateTimeAPI->Time_FromTime(hour, minute, second, usecond, \
		Py_None, PyDateTimeAPI->TimeType)

#define PyDelta_FromDSU(days, seconds, useconds) \
228
	PyDateTimeAPI->Delta_FromDelta(days, seconds, useconds, 1, \
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
		PyDateTimeAPI->DeltaType)

/* Macros supporting the DB API. */
#define PyDateTime_FromTimestamp(args) \
	PyDateTimeAPI->DateTime_FromTimestamp( \
		(PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL)

#define PyDate_FromTimestamp(args) \
	PyDateTimeAPI->Date_FromTimestamp( \
		(PyObject*) (PyDateTimeAPI->DateType), args)

#endif	/* Py_BUILD_CORE */

#ifdef __cplusplus
}
#endif
245
#endif