[Python-checkins] CVS: python/nondist/sandbox/datetime datetime.c,1.4,1.5

Fred L. Drake fdrake@users.sourceforge.net
Tue, 05 Mar 2002 20:30:53 -0800


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

Modified Files:
	datetime.c 
Log Message:
Fix SET_MICROSECOND() macro to actually store the value correctly.

Add support for isoformat(), isoweekday(), weekday().
Added class attributes min, max.

Moved instance creation to a separate function from the tp_new
handler; this makes it easier to create instances using alternate
constructors, or just in C code.


Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** datetime.c	6 Mar 2002 04:05:59 -0000	1.4
--- datetime.c	6 Mar 2002 04:30:51 -0000	1.5
***************
*** 29,34 ****
  #define SET_SECOND(o, v)      (PyDateTime_GET_SECOND(o) = (v))
  #define SET_MICROSECOND(o, v) (((o)->data[7] = ((v) & 0xff0000) >> 16), \
!                                ((o)->data[8] = ((v) & 0x00ff00) >> 0), \
!                                ((o)->data[9] = ((v) & 0x00ff00)))
  
  static PyObject *
--- 29,103 ----
  #define SET_SECOND(o, v)      (PyDateTime_GET_SECOND(o) = (v))
  #define SET_MICROSECOND(o, v) (((o)->data[7] = ((v) & 0xff0000) >> 16), \
!                                ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
!                                ((o)->data[9] = ((v) & 0x0000ff)))
! 
! /*
!  * General calendrical helper functions
!  */
! 
! static int
! is_leap(int year)
! {
!     return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
! }
! 
! static int
! days_in_month(int year, int month)
! {
!     static int _days_in_month[] = {
!         0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
!     };
! 
!     assert(month >= 1);
!     assert(month <= 12);
!     if (month == 2 && is_leap(year))
!         return 29;
!     else
!         return _days_in_month[month];
! }
! 
! static long
! days_before_year(int year)
! {
!     int y = year - 1;
!     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)
! {
!     int days;
! 
!     assert(month >= 1);
!     assert(month <= 12);
!     days = _days_before_month[month];
!     if (month > 2 && is_leap(year))
!         ++days;
!     return days;
! }
! 
! static long
! ymd_to_ord(int year, int month, int day)
! {
!     return days_before_year(year) + days_before_month(year, month) + day;
! }
! 
! static int
! weekday(int year, int month, int day)
! {
!     return (ymd_to_ord(year, month, day) + 6) % 7;
! }
! 
! 
! /*
!  * PyDateTime_Object implementation
!  */
  
  static PyObject *
***************
*** 58,80 ****
  }
  
! static int
! is_leap(int year)
! {
!     return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
! }
! 
! static int
! days_in_month(int year, int month)
  {
!     static int _days_in_month[] = {
!         0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
!     };
  
!     assert(month >= 1);
!     assert(month <= 12);
!     if (month == 2 && is_leap(year))
!         return 29;
!     else
!         return _days_in_month[month];
  }
  
--- 127,148 ----
  }
  
! /* Create a datetime instance with no range checking. */
! static PyObject *
! new_datetime(int year, int month, int day, int hour, int minute,
!              int second, int usecond)
  {
!     PyDateTime_Object *self;
  
!     self = PyObject_New(PyDateTime_Object, &PyDateTime_Type);
!     if (self != NULL) {
!         SET_YEAR(self, year);
!         SET_MONTH(self, month);
!         SET_DAY(self, day);
!         SET_HOUR(self, hour);
!         SET_MINUTE(self, minute);
!         SET_SECOND(self, second);
!         SET_MICROSECOND(self, usecond);
!     }
!     return (PyObject *) self;
  }
  
***************
*** 82,89 ****
  datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  {
!     PyDateTime_Object *self = NULL;
      long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0;
  
!     static char * keywords[] = {
          "year", "month", "day", "hour", "minute", "second", "microsecond", NULL
      };
--- 150,157 ----
  datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  {
!     PyObject *self = NULL;
      long int year, month, day, hour = 0, minute = 0, second = 0, usecond = 0;
  
!     static char *keywords[] = {
          "year", "month", "day", "hour", "minute", "second", "microsecond", NULL
      };
***************
*** 121,136 ****
              return NULL;
          }
!         self = PyObject_New(PyDateTime_Object, &PyDateTime_Type);
!         if (self != NULL) {
!             SET_YEAR(self, year);
!             SET_MONTH(self, month);
!             SET_DAY(self, day);
!             SET_HOUR(self, hour);
!             SET_MINUTE(self, minute);
!             SET_SECOND(self, second);
!             SET_MICROSECOND(self, usecond);
!         }
      }
!     return (PyObject *) self;
  }
  
--- 189,195 ----
              return NULL;
          }
!         self = new_datetime(year, month, day, hour, minute, second, usecond);
      }
!     return self;
  }
  
***************
*** 189,192 ****
--- 248,300 ----
  };
  
+ static PyObject *
+ datetime_isoformat(PyDateTime_Object *self, PyObject *args, PyObject *kw)
+ {
+     char buffer[128];
+     char sep = 'T';
+ 
+     static char *keywords[] = {"sep", NULL};
+ 
+     if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords, &sep))
+         return NULL;
+ 
+     PyOS_snprintf(buffer, sizeof(buffer),
+                   "%04d-%02d-%02d%c%02d:%02d:%02d.%06d",
+                   GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
+                   sep,
+                   GET_HOUR(self), GET_MINUTE(self), GET_SECOND(self),
+                   GET_MICROSECOND(self));
+     return PyString_FromString(buffer);
+ }
+ 
+ static PyObject *
+ datetime_isoweekday(PyDateTime_Object *self)
+ {
+     int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
+ 
+     return PyInt_FromLong(dow + 1);
+ }
+ 
+ static PyObject *
+ datetime_weekday(PyDateTime_Object *self)
+ {
+     int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
+ 
+     return PyInt_FromLong(dow);
+ }
+ 
+ static PyMethodDef datetime_methods[] = {
+     {"isoformat",   (PyCFunction)datetime_isoformat,  METH_VARARGS|METH_KEYWORDS,
+      "Return the day of the week represented by the datetime.\n"
+      "Monday == 1 ... Sunday == 7"},
+     {"isoweekday",  (PyCFunction)datetime_isoweekday, METH_NOARGS,
+      "Return the day of the week represented by the datetime.\n"
+      "Monday == 1 ... Sunday == 7"},
+     {"weekday",     (PyCFunction)datetime_weekday,    METH_NOARGS,
+      "Return the day of the week represented by the datetime.\n"
+      "Monday == 0 ... Sunday == 6"},
+     {NULL}
+ };
+ 
  static char datetime_doc[] =
  "Basic date/time type.";
***************
*** 223,227 ****
      0,						/* tp_iter */
      0,						/* tp_iternext */
!     0,						/* tp_methods */
      0,						/* tp_members */
      datetime_getset,				/* tp_getset */
--- 331,335 ----
      0,						/* tp_iter */
      0,						/* tp_iternext */
!     datetime_methods,				/* tp_methods */
      0,						/* tp_members */
      datetime_getset,				/* tp_getset */
***************
*** 242,246 ****
      {NULL, NULL, 0, NULL}
  };
!     
  
  void
--- 350,354 ----
      {NULL, NULL, 0, NULL}
  };
! 
  
  void
***************
*** 248,254 ****
--- 356,373 ----
  {
      PyObject *m;
+     PyObject *d, *dt;
  
      if (PyType_Ready(&PyDateTime_Type) < 0)
          return;
+ 
+     d = PyDateTime_Type.tp_dict;
+     dt = new_datetime(1, 1, 1, 0, 0, 0, 0);
+     if (dt == NULL || PyDict_SetItemString(d, "min", dt) < 0)
+         return;
+     Py_DECREF(dt);
+     dt = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999);
+     if (dt == NULL || PyDict_SetItemString(d, "max", dt) < 0)
+         return;
+     Py_DECREF(dt);
  
      m = Py_InitModule3("_datetime", functions,