4988 lines · 135.1 KB · C
RawDownload
/*  C implementation for the date/time type documented at *  http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage */ #include "Python.h"#include "modsupport.h"#include "structmember.h" #include <time.h> #include "timefuncs.h" /* Differentiate between building the core module and building extension * modules. */#define Py_BUILD_CORE#include "datetime.h"#undef Py_BUILD_CORE /* We require that C int be at least 32 bits, and use int virtually * everywhere.  In just a few cases we use a temp long, where a Python * API returns a C long.  In such cases, we have to ensure that the * final result fits in a C int (this can be an issue on 64-bit boxes). */#if SIZEOF_INT < 4#	error "datetime.c requires that C int have at least 32 bits"#endif #define MINYEAR 1#define MAXYEAR 9999 /* Nine decimal digits is easy to communicate, and leaves enough room * so that two delta days can be added w/o fear of overflowing a signed * 32-bit int, and with plenty of room left over to absorb any possible * carries from adding seconds. */#define MAX_DELTA_DAYS 999999999 /* Rename the long macros in datetime.h to more reasonable short names. */#define GET_YEAR		PyDateTime_GET_YEAR#define GET_MONTH		PyDateTime_GET_MONTH#define GET_DAY			PyDateTime_GET_DAY#define DATE_GET_HOUR		PyDateTime_DATE_GET_HOUR#define DATE_GET_MINUTE		PyDateTime_DATE_GET_MINUTE#define DATE_GET_SECOND		PyDateTime_DATE_GET_SECOND#define DATE_GET_MICROSECOND	PyDateTime_DATE_GET_MICROSECOND /* Date accessors for date and datetime. */#define SET_YEAR(o, v)		(((o)->data[0] = ((v) & 0xff00) >> 8), \                                 ((o)->data[1] = ((v) & 0x00ff)))#define SET_MONTH(o, v)		(PyDateTime_GET_MONTH(o) = (v))#define SET_DAY(o, v)		(PyDateTime_GET_DAY(o) = (v)) /* Date/Time accessors for datetime. */#define DATE_SET_HOUR(o, v)	(PyDateTime_DATE_GET_HOUR(o) = (v))#define DATE_SET_MINUTE(o, v)	(PyDateTime_DATE_GET_MINUTE(o) = (v))#define DATE_SET_SECOND(o, v)	(PyDateTime_DATE_GET_SECOND(o) = (v))#define DATE_SET_MICROSECOND(o, v)	\	(((o)->data[7] = ((v) & 0xff0000) >> 16), \         ((o)->data[8] = ((v) & 0x00ff00) >> 8), \         ((o)->data[9] = ((v) & 0x0000ff))) /* Time accessors for time. */#define TIME_GET_HOUR		PyDateTime_TIME_GET_HOUR#define TIME_GET_MINUTE		PyDateTime_TIME_GET_MINUTE#define TIME_GET_SECOND		PyDateTime_TIME_GET_SECOND#define TIME_GET_MICROSECOND	PyDateTime_TIME_GET_MICROSECOND#define TIME_SET_HOUR(o, v)	(PyDateTime_TIME_GET_HOUR(o) = (v))#define TIME_SET_MINUTE(o, v)	(PyDateTime_TIME_GET_MINUTE(o) = (v))#define TIME_SET_SECOND(o, v)	(PyDateTime_TIME_GET_SECOND(o) = (v))#define TIME_SET_MICROSECOND(o, v)	\	(((o)->data[3] = ((v) & 0xff0000) >> 16), \         ((o)->data[4] = ((v) & 0x00ff00) >> 8), \         ((o)->data[5] = ((v) & 0x0000ff))) /* Delta accessors for timedelta. */#define GET_TD_DAYS(o)		(((PyDateTime_Delta *)(o))->days)#define GET_TD_SECONDS(o)	(((PyDateTime_Delta *)(o))->seconds)#define GET_TD_MICROSECONDS(o)	(((PyDateTime_Delta *)(o))->microseconds) #define SET_TD_DAYS(o, v)	((o)->days = (v))#define SET_TD_SECONDS(o, v)	((o)->seconds = (v))#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v)) /* p is a pointer to a time or a datetime object; HASTZINFO(p) returns * p->hastzinfo. */#define HASTZINFO(p)		(((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) /* M is a char or int claiming to be a valid month.  The macro is equivalent * to the two-sided Python test *	1 <= M <= 12 */#define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) /* Forward declarations. */static PyTypeObject PyDateTime_DateType;static PyTypeObject PyDateTime_DateTimeType;static PyTypeObject PyDateTime_DeltaType;static PyTypeObject PyDateTime_TimeType;static PyTypeObject PyDateTime_TZInfoType; /* --------------------------------------------------------------------------- * Math utilities. */ /* k = i+j overflows iff k differs in sign from both inputs, * iff k^i has sign bit set and k^j has sign bit set, * iff (k^i)&(k^j) has sign bit set. */#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \	((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0) /* Compute Python divmod(x, y), returning the quotient and storing the * remainder into *r.  The quotient is the floor of x/y, and that's * the real point of this.  C will probably truncate instead (C99 * requires truncation; C89 left it implementation-defined). * Simplification:  we *require* that y > 0 here.  That's appropriate * for all the uses made of it.  This simplifies the code and makes * the overflow case impossible (divmod(LONG_MIN, -1) is the only * overflow case). */static intdivmod(int x, int y, int *r){	int quo; 	assert(y > 0);	quo = x / y;	*r = x - quo * y;	if (*r < 0) {		--quo;		*r += y;	}	assert(0 <= *r && *r < y);	return quo;} /* Round a double to the nearest long.  |x| must be small enough to fit * in a C long; this is not checked. */static longround_to_long(double x){	if (x >= 0.0)		x = floor(x + 0.5);	else		x = ceil(x - 0.5);	return (long)x;} /* --------------------------------------------------------------------------- * General calendrical helper functions */ /* For each month ordinal in 1..12, the number of days in that month, * and the number of days before that month in the same year.  These * are correct for non-leap years only. */static int _days_in_month[] = {	0, /* unused; this vector uses 1-based indexing */	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static int _days_before_month[] = {	0, /* unused; this vector uses 1-based indexing */	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; /* year -> 1 if leap year, else 0. */static intis_leap(int year){	/* Cast year to unsigned.  The result is the same either way, but	 * C can generate faster code for unsigned mod than for signed	 * mod (especially for % 4 -- a good compiler should just grab	 * the last 2 bits when the LHS is unsigned).	 */	const unsigned int ayear = (unsigned int)year;	return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);} /* year, month -> number of days in that month in that year */static intdays_in_month(int year, int month){	assert(month >= 1);	assert(month <= 12);	if (month == 2 && is_leap(year))		return 29;	else		return _days_in_month[month];} /* year, month -> number of days in year preceeding first day of month */static intdays_before_month(int year, int month){	int days; 	assert(month >= 1);	assert(month <= 12);	days = _days_before_month[month];	if (month > 2 && is_leap(year))		++days;	return days;} /* year -> number of days before January 1st of year.  Remember that we * start with year 1, so days_before_year(1) == 0. */static intdays_before_year(int year){	int y = year - 1;	/* This is incorrect if year <= 0; we really want the floor	 * here.  But so long as MINYEAR is 1, the smallest year this	 * can see is 0 (this can happen in some normalization endcases),	 * so we'll just special-case that.	 */	assert (year >= 0);	if (y >= 0)		return y*365 + y/4 - y/100 + y/400;	else {		assert(y == -1);		return -366;	}} /* Number of days in 4, 100, and 400 year cycles.  That these have * the correct values is asserted in the module init function. */#define DI4Y	1461	/* days_before_year(5); days in 4 years */#define DI100Y	36524	/* days_before_year(101); days in 100 years */#define DI400Y	146097	/* days_before_year(401); days in 400 years  */ /* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */static voidord_to_ymd(int ordinal, int *year, int *month, int *day){	int n, n1, n4, n100, n400, leapyear, preceding; 	/* ordinal is a 1-based index, starting at 1-Jan-1.  The pattern of	 * leap years repeats exactly every 400 years.  The basic strategy is	 * to find the closest 400-year boundary at or before ordinal, then	 * work with the offset from that boundary to ordinal.  Life is much	 * clearer if we subtract 1 from ordinal first -- then the values	 * of ordinal at 400-year boundaries are exactly those divisible	 * by DI400Y:	 *	 *    D  M   Y            n              n-1	 *    -- --- ----        ----------     ----------------	 *    31 Dec -400        -DI400Y       -DI400Y -1	 *     1 Jan -399         -DI400Y +1   -DI400Y      400-year boundary	 *    ...	 *    30 Dec  000        -1             -2	 *    31 Dec  000         0             -1	 *     1 Jan  001         1              0          400-year boundary	 *     2 Jan  001         2              1	 *     3 Jan  001         3              2	 *    ...	 *    31 Dec  400         DI400Y        DI400Y -1	 *     1 Jan  401         DI400Y +1     DI400Y      400-year boundary	 */	assert(ordinal >= 1);	--ordinal;	n400 = ordinal / DI400Y;	n = ordinal % DI400Y;	*year = n400 * 400 + 1; 	/* Now n is the (non-negative) offset, in days, from January 1 of	 * year, to the desired date.  Now compute how many 100-year cycles	 * precede n.	 * Note that it's possible for n100 to equal 4!  In that case 4 full	 * 100-year cycles precede the desired day, which implies the	 * desired day is December 31 at the end of a 400-year cycle.	 */	n100 = n / DI100Y;	n = n % DI100Y; 	/* Now compute how many 4-year cycles precede it. */	n4 = n / DI4Y;	n = n % DI4Y; 	/* And now how many single years.  Again n1 can be 4, and again	 * meaning that the desired day is December 31 at the end of the	 * 4-year cycle.	 */	n1 = n / 365;	n = n % 365; 	*year += n100 * 100 + n4 * 4 + n1;	if (n1 == 4 || n100 == 4) {		assert(n == 0);		*year -= 1;		*month = 12;		*day = 31;		return;	} 	/* Now the year is correct, and n is the offset from January 1.  We	 * find the month via an estimate that's either exact or one too	 * large.	 */	leapyear = n1 == 3 && (n4 != 24 || n100 == 3);	assert(leapyear == is_leap(*year));	*month = (n + 50) >> 5;	preceding = (_days_before_month[*month] + (*month > 2 && leapyear));	if (preceding > n) {		/* estimate is too large */		*month -= 1;		preceding -= days_in_month(*year, *month);	}	n -= preceding;	assert(0 <= n);	assert(n < days_in_month(*year, *month)); 	*day = n + 1;} /* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */static intymd_to_ord(int year, int month, int day){	return days_before_year(year) + days_before_month(year, month) + day;} /* Day of week, where Monday==0, ..., Sunday==6.  1/1/1 was a Monday. */static intweekday(int year, int month, int day){	return (ymd_to_ord(year, month, day) + 6) % 7;} /* Ordinal of the Monday starting week 1 of the ISO year.  Week 1 is the * first calendar week containing a Thursday. */static intiso_week1_monday(int year){	int first_day = ymd_to_ord(year, 1, 1);	/* ord of 1/1 */	/* 0 if 1/1 is a Monday, 1 if a Tue, etc. */	int first_weekday = (first_day + 6) % 7;	/* ordinal of closest Monday at or before 1/1 */	int week1_monday  = first_day - first_weekday; 	if (first_weekday > 3)	/* if 1/1 was Fri, Sat, Sun */		week1_monday += 7;	return week1_monday;} /* --------------------------------------------------------------------------- * Range checkers. */ /* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS.  If so, return 0. * If not, raise OverflowError and return -1. */static intcheck_delta_day_range(int days){	if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)		return 0;	PyErr_Format(PyExc_OverflowError,		     "days=%d; must have magnitude <= %d",		     days, MAX_DELTA_DAYS);	return -1;} /* Check that date arguments are in range.  Return 0 if they are.  If they * aren't, raise ValueError and return -1. */static intcheck_date_args(int year, int month, int day){ 	if (year < MINYEAR || year > MAXYEAR) {		PyErr_SetString(PyExc_ValueError,				"year is out of range");		return -1;	}	if (month < 1 || month > 12) {		PyErr_SetString(PyExc_ValueError,				"month must be in 1..12");		return -1;	}	if (day < 1 || day > days_in_month(year, month)) {		PyErr_SetString(PyExc_ValueError,				"day is out of range for month");		return -1;	}	return 0;} /* Check that time arguments are in range.  Return 0 if they are.  If they * aren't, raise ValueError and return -1. */static intcheck_time_args(int h, int m, int s, int us){	if (h < 0 || h > 23) {		PyErr_SetString(PyExc_ValueError,				"hour must be in 0..23");		return -1;	}	if (m < 0 || m > 59) {		PyErr_SetString(PyExc_ValueError,				"minute must be in 0..59");		return -1;	}	if (s < 0 || s > 59) {		PyErr_SetString(PyExc_ValueError,				"second must be in 0..59");		return -1;	}	if (us < 0 || us > 999999) {		PyErr_SetString(PyExc_ValueError,				"microsecond must be in 0..999999");		return -1;	}	return 0;} /* --------------------------------------------------------------------------- * Normalization utilities. */ /* One step of a mixed-radix conversion.  A "hi" unit is equivalent to * factor "lo" units.  factor must be > 0.  If *lo is less than 0, or * at least factor, enough of *lo is converted into "hi" units so that * 0 <= *lo < factor.  The input values must be such that int overflow * is impossible. */static voidnormalize_pair(int *hi, int *lo, int factor){	assert(factor > 0);	assert(lo != hi);	if (*lo < 0 || *lo >= factor) {		const int num_hi = divmod(*lo, factor, lo);		const int new_hi = *hi + num_hi;		assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));		*hi = new_hi;	}	assert(0 <= *lo && *lo < factor);} /* Fiddle days (d), seconds (s), and microseconds (us) so that * 	0 <= *s < 24*3600 * 	0 <= *us < 1000000 * The input values must be such that the internals don't overflow. * The way this routine is used, we don't get close. */static voidnormalize_d_s_us(int *d, int *s, int *us){	if (*us < 0 || *us >= 1000000) {		normalize_pair(s, us, 1000000);		/* |s| can't be bigger than about		 * |original s| + |original us|/1000000 now.		 */ 	}	if (*s < 0 || *s >= 24*3600) {		normalize_pair(d, s, 24*3600);		/* |d| can't be bigger than about		 * |original d| +		 * (|original s| + |original us|/1000000) / (24*3600) now.		 */	}	assert(0 <= *s && *s < 24*3600);	assert(0 <= *us && *us < 1000000);} /* Fiddle years (y), months (m), and days (d) so that * 	1 <= *m <= 12 * 	1 <= *d <= days_in_month(*y, *m) * The input values must be such that the internals don't overflow. * The way this routine is used, we don't get close. */static voidnormalize_y_m_d(int *y, int *m, int *d){	int dim;	/* # of days in month */ 	/* This gets muddy:  the proper range for day can't be determined	 * without knowing the correct month and year, but if day is, e.g.,	 * plus or minus a million, the current month and year values make	 * no sense (and may also be out of bounds themselves).	 * Saying 12 months == 1 year should be non-controversial.	 */	if (*m < 1 || *m > 12) {		--*m;		normalize_pair(y, m, 12);		++*m;		/* |y| can't be bigger than about		 * |original y| + |original m|/12 now.		 */	}	assert(1 <= *m && *m <= 12);

Lines 1–500 of 4988.