[Python-checkins] python/nondist/sandbox/datetime datetime.c,1.22,1.23 datetime.h,1.9,1.10 datetime.py,1.63,1.64

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Thu, 21 Nov 2002 19:34:44 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv26013

Modified Files:
	datetime.c datetime.h datetime.py 
Log Message:
Copied over many comments from the .py version -- much of this code is
incomprehensible without them.  Fixed some typos and misdeclarations.


Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -C2 -d -r1.22 -r1.23
*** datetime.c	22 Nov 2002 02:59:56 -0000	1.22
--- datetime.c	22 Nov 2002 03:34:42 -0000	1.23
***************
*** 17,24 ****
  {
  	PyObject_HEAD
! 	int hashcode;
! 	long int days;
! 	long int seconds;
! 	long int microseconds;
  } PyDateTime_Delta;
  
--- 17,24 ----
  {
  	PyObject_HEAD
! 	long hashcode;
! 	long days;
! 	long seconds;
! 	long microseconds;
  } PyDateTime_Delta;
  
***************
*** 64,67 ****
--- 64,82 ----
   */
  
+ /* 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 int
  is_leap(int year)
***************
*** 76,87 ****
  }
  
  static int
  days_in_month(int year, int month)
  {
- 	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
- 	};
- 
  	assert(month >= 1);
  	assert(month <= 12);
--- 91,98 ----
  }
  
+ /* month, year -> number of days in that month in that year */
  static int
  days_in_month(int year, int month)
  {
  	assert(month >= 1);
  	assert(month <= 12);
***************
*** 92,114 ****
  }
  
! static long
! days_before_year(int year)
! {
! 	int y = year - 1;
! 	/* XXX This is incorrect if year <= 0; we really want the floor
! 	 * XXX here.
! 	 * XXX If we're sticking to strictly positive years, it would be
! 	 * XXX better to change all these signatures to use unsigned ints.
! 	 */
! 	return y*365 + y/4 - y/100 + y/400;
! }
! 
! /* Each entry at index 1..12 gives the number of days before each
!  * month on non-leap years.
!  */
! static int _days_before_month[] = {
! 	0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
! };
! 
  static int
  days_before_month(int year, int month)
--- 103,107 ----
  }
  
! /* month, year -> number of days in year preceeding first day of month */
  static int
  days_before_month(int year, int month)
***************
*** 124,127 ****
--- 117,137 ----
  }
  
+ /* year -> number of days before January 1st of year.  Remember that we
+  * start with year 1, so days_before_year(1) == 0.
+  */
+ static long
+ days_before_year(int year)
+ {
+ 	int y = year - 1;
+ 	/* XXX This is incorrect if year <= 0; we really want the floor
+ 	 * XXX here.
+ 	 * XXX If we're sticking to strictly positive years, it would be
+ 	 * XXX better to change all these signatures to use unsigned ints.
+ 	 */
+ 	assert(year > 0);
+ 	return y*365 + y/4 - y/100 + y/400;
+ }
+ 
+ 
  /* Number of days in 4, 100, and 400 year cycles.  That these have
   * the correct values is asserted in the module init function.
***************
*** 133,140 ****
  /* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
  static void
! ord_to_ymd(long    ordinal, long *year, long *month, long *day)
  {
  	int n, n1, n4, n100, n400, leapyear, preceding;
  
  	assert(ordinal >= 1);
  	--ordinal;
--- 143,172 ----
  /* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
  static void
! ord_to_ymd(long      ordinal, long *year, long *month, long *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;
***************
*** 143,152 ****
--- 175,196 ----
  	*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;
***************
*** 160,163 ****
--- 204,212 ----
  		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));
***************
*** 183,186 ****
--- 232,236 ----
  }
  
+ /* Day of week, where Monday==0, ..., Sunday==6.  1/1/1 was a Monday. */
  static int
  weekday(int year, int month, int day)

Index: datetime.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -C2 -d -r1.9 -r1.10
*** datetime.h	21 Nov 2002 22:55:26 -0000	1.9
--- datetime.h	22 Nov 2002 03:34:42 -0000	1.10
***************
*** 5,9 ****
--- 5,27 ----
  #define DATETIME_H
  
+ /* 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  		tzoffset 2 bytes, signed, in minutes, -1439 .. 1439
+  * 12
+  */
+ 
+ /* # of bytes for year, month, and day. */
  #define _PyDateTime_DATE_DATA_SIZE 4
+ 
+ /* # of bytes for year, month, day, hour, minute, second, and usecond. */
  #define _PyDateTime_DATETIME_DATA_SIZE 10
  

Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.63
retrieving revision 1.64
diff -C2 -d -r1.63 -r1.64
*** datetime.py	20 Nov 2002 03:23:34 -0000	1.63
--- datetime.py	22 Nov 2002 03:34:42 -0000	1.64
***************
*** 655,659 ****
  
          The first ISO week of the year is the (Mon-Sun) week
!         containing the year's first Thursday; everything rest derives
          from that.
  
--- 655,659 ----
  
          The first ISO week of the year is the (Mon-Sun) week
!         containing the year's first Thursday; everything else derives
          from that.