[Zope3-checkins] CVS: Zope3/src/datetime - __init__.py:1.1.2.1 _datetime.py:1.1.2.1 doc.txt:1.1.2.1

Jim Fulton jim@zope.com
Mon, 23 Dec 2002 14:30:39 -0500


Update of /cvs-repository/Zope3/src/datetime
In directory cvs.zope.org:/tmp/cvs-serv19908/datetime

Added Files:
      Tag: NameGeddon-branch
	__init__.py _datetime.py doc.txt 
Log Message:
Initial renaming before debugging

=== Added File Zope3/src/datetime/__init__.py ===
# Python datetime prototype.

# This package contains the prototype datetime Python module whose C
# version is included in Python 2.3.  We've turned it into a package to
# make it easier to deal with in CVS for now.  This __init__ file makes the
# package look like the eventual module.

from datetime._datetime import MINYEAR, MAXYEAR
from datetime._datetime import timedelta
from datetime._datetime import time, timetz
from datetime._datetime import date, datetime, datetimetz
from datetime._datetime import tzinfo


=== Added File Zope3/src/datetime/_datetime.py === (1634/1734 lines abridged)
"""Concrete date/time and related types -- prototype implemented in Python.

See http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage

See also http://dir.yahoo.com/Reference/calendars/
"""

import time as _time
import math as _math

MINYEAR = 1     # XXX The design doc says 0
MAXYEAR = 9999  # XXX The design doc says 65535

# Utility functions, adapted from Python's Demo/classes/Dates.py, which
# also assumes the current Gregorian calendar indefinitely extended in
# both directions.  Difference:  Dates.py calls January 1 of year 0 day
# number 1.  The code here calls January 1 of year 1 day number 1.  This is
# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
# and Reingold's "Calendrical Calculations", where it's the base calendar
# for all computations.  See the book for algorithms for converting between
# proleptic Gregorian ordinals and many other calendar systems.

_DAYS_IN_MONTH = [None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

_DAYS_BEFORE_MONTH = [None]
dbm = 0
for dim in _DAYS_IN_MONTH[1:]:
    _DAYS_BEFORE_MONTH.append(dbm)
    dbm += dim
del dbm, dim

def _is_leap(year):
    "year -> 1 if leap year, else 0."
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

def _days_in_year(year):
    "year -> number of days in year (366 if a leap year, else 365)."
    return 365 + _is_leap(year)

def _days_before_year(year):
    "year -> number of days before January 1st of year."
    y = year - 1
    return y*365 + y//4 - y//100 + y//400

def _days_in_month(year, month):
    "year, month -> number of days in that month in that year."
    assert 1 <= month <= 12, month
    if month == 2 and _is_leap(year):
        return 29
    return _DAYS_IN_MONTH[month]

[-=- -=- -=- 1634 lines omitted -=- -=- -=-]

def _time_pickler(t):
    state = t.__getstate__()
    return _time_unpickler, (state,)

def _time_unpickler(state):
    self = time()
    self.__setstate__(state)
    return self

def _tzinfo_pickler(tz):
    return _tzinfo_unpickler, ()

def _tzinfo_unpickler():
    self = tzinfo()
    return self

def _timetz_pickler(tz):
    state = tz.__getstate__()
    return _timetz_unpickler, (state,)

def _timetz_unpickler(state):
    self = timetz()
    self.__setstate__(state)
    return self

def _datetimetz_pickler(dtz):
    state = dtz.__getstate__()
    return _datetimetz_unpickler, (state,)

def _datetimetz_unpickler(state):
    self = datetimetz(1, 1, 1)
    self.__setstate__(state)
    return self

# Register pickle/unpickle functions.
from copy_reg import pickle
pickle(date, _date_pickler, _date_unpickler)
pickle(datetime, _datetime_pickler, _datetime_unpickler)
pickle(time, _time_pickler, _time_unpickler)
pickle(tzinfo, _tzinfo_pickler, _tzinfo_unpickler)
pickle(timetz, _timetz_pickler, _timetz_unpickler)
pickle(datetimetz, _datetimetz_pickler, _datetimetz_unpickler)
del pickle

def _test():
    import test_datetime
    test_datetime.test_main()

if __name__ == "__main__":
    _test()


=== Added File Zope3/src/datetime/doc.txt === (1096/1196 lines abridged)
TODO/OPEN
=========
- The Python implementation is missing docstrings in many places.

- LaTeXize the docs.


CLOSED
======
- Pickle incompatibility?  It occurs to me that, because the
  implementations are so different, a pickle created by the Python
  implementation won't be unpicklable by the C implementation, or vice
  versa.  If this is important, the Python implementation will have to
  change, as the C implementation of pickling took days to get working
  and has no wiggle room (TOOWTDI indeed <wink>).

  Resolution:  Jim Fulton suggested adding various __reduce__ methods
  to the Python implementation, and that did lead to pickles that the
  C implementation groks.  I'm not sure why, and tzinfo subclasses must
  have an __init__ that can be called without arguments now (if
  they want to play with pickles).  It appears they must also set
  class attr __safe_for_unpickling__ = True, but only if they want a
  pickle written by the Python implementation to be readable by the C
  implementation.

- The test suite doesn't pass under 2.2.2, due to what Guido tracked
  to a bug in 2.2.2's implementation of __cmp__ for new-style classes.
  Later:  the test suite grew a version check to avoid provoking this
  bug under 2.2.2.

- What should str() do?  It generally acts like a synonym for isoformat()
  now.  But

    >>> print time(2)
    02:00:00.000000
    >>>

  is arguably better as '2:00:00' or even '2:00'.  The Python
  implementation has (overridden) "pretty __str__" according to one
  person's idea of "pretty", for a couple types.  Rat hole.
  Guido sez:  chop ".000000" when microseconds are 0, and that's it.
  Tim sez:  and having a fixed-size string when they are will make
  life easier for people implementing their own ideas of "pretty".
  Later:  isoformat() should also elide trailing microsecond when it's
  0.
  Done.

- pickles still "feel too big".  But this is a general issue w/ new-style
  classes.


[-=- -=- -=- 1096 lines omitted -=- -=- -=-]

    PyDateTime_DateTimeTZ
    PyDateTime_Time
    PyDateTime_TimeTZ
    PyDateTime_Delta
    PyDateTime_TZInfo

Type-check macros:

    PyDate_Check(op)
    PyDate_CheckExact(op)

    PyDateTime_Check(op)
    PyDateTime_CheckExact(op)

    PyDateTimeTZ_Check(op)
    PyDateTimeTZ_CheckExact(op)

    PyTime_Check(op)
    PyTime_CheckExact(op)

    PyTimeTZ_Check(op)
    PyTimeTZ_CheckExact(op)

    PyDelta_Check(op)
    PyDelta_CheckExact(op)

    PyTZInfo_Check(op)
    PyTZInfo_CheckExact(op

Accessor macros:

All objects are immutable, so accessors are read-only.  All macros
return ints:

    For date, datetime, and datetimetz instances:
        PyDateTime_GET_YEAR(o)
        PyDateTime_GET_MONTH(o)
        PyDateTime_GET_DAY(o)

    For datetime and datetimetz instances:
        PyDateTime_DATE_GET_HOUR(o)
        PyDateTime_DATE_GET_MINUTE(o)
        PyDateTime_DATE_GET_SECOND(o)
        PyDateTime_DATE_GET_MICROSECOND(o)

    For time and timetz instances:
        PyDateTime_TIME_GET_HOUR(o)
        PyDateTime_TIME_GET_MINUTE(o)
        PyDateTime_TIME_GET_SECOND(o)
        PyDateTime_TIME_GET_MICROSECOND(o)