[Python-checkins] CVS: python/nondist/sandbox/datetime datetime.py,1.53,1.54 test_datetime.py,1.37,1.38
Guido van Rossum
gvanrossum@users.sourceforge.net
Tue, 05 Mar 2002 17:25:18 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory usw-pr-cvs1:/tmp/cvs-serv5073
Modified Files:
datetime.py test_datetime.py
Log Message:
Eradicate all references to time zone offset.
This implements naive time'' as I described on python-dev.
Some cleanup remains to be done...
Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.53
retrieving revision 1.54
diff -C2 -d -r1.53 -r1.54
*** datetime.py 5 Mar 2002 19:11:43 -0000 1.53
--- datetime.py 6 Mar 2002 01:25:13 -0000 1.54
***************
*** 249,267 ****
- def _localtzoffset(year, month, day, hour, minute):
- "Return tzoffset for local time corresponding to given date/time."
- try:
- t = _time.mktime((year, month, day, hour, minute, 0, -1, -1, -1))
- tm = _time.localtime(t)
- if tm.tm_isdst > 0:
- return - (_time.altzone // 60)
- else:
- return - (_time.timezone // 60)
- except (ValueError, OverflowError):
- # Dates out of range for mktime() never see DST.
- # As a reasonable guess, though, we can try a year in mktime()'s range
- # with the same leap-year-ness as the given year.
- return _localtzoffset(2003 + _is_leap(year), month, day, hour, minute)
-
class basetime(object):
"""Abstract date/time type.
--- 249,252 ----
***************
*** 423,443 ****
def __str__(self):
! def plural(n):
! return n, n != 1 and "s" or ""
! L = []
if self.__days:
! L.append("%d day%s" % plural(self.__days))
! if self.__seconds:
! mm, ss = divmod(self.__seconds, 60)
! hh, mm = divmod(mm, 60)
! if hh:
! L.append("%d hour%s" % plural(hh))
! if mm:
! L.append("%d minute%s" % plural(mm))
! if ss:
! L.append("%d second%s" % plural(ss))
if self.__microseconds:
! L.append("%d microsecond%s" % plural(self.__microseconds))
! return ", ".join(L)
days = property(lambda self: self.__days, doc="days")
--- 408,421 ----
def __str__(self):
! mm, ss = divmod(self.__seconds, 60)
! hh, mm = divmod(mm, 60)
! s = "%d:%02d:%02d" % (hh, mm, ss)
if self.__days:
! def plural(n):
! return n, n != 1 and "s" or ""
! s = ("%d day%s, " % plural(self.__days)) + s
if self.__microseconds:
! s = s + ".%06d" % self.__microseconds
! return s
days = property(lambda self: self.__days, doc="days")
***************
*** 560,568 ****
"Construct a date from a POSIX timestamp (like time.time())."
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
- us = int((t % 1.0) * 1000000)
- if dst > 0:
- tz = -(_time.altzone // 60)
- else:
- tz = -(_time.timezone // 60)
return cls(y, m, d)
fromtimestamp = classmethod(fromtimestamp)
--- 538,541 ----
***************
*** 636,642 ****
def __hash__(self):
"Hash."
- # Caution: objects that compare equal must have equal hashcodes,
- # and two dates can be equal even if their fields aren't
- # (due to tzoffset). So we have to compute a UTC-normalized hash.
return hash((self.__year, self.__month, self.__day))
--- 609,612 ----
***************
*** 648,662 ****
# strftime("%c", ...) is locale specific.
- # XXX An additional question is whether ctime() should renormalize
- # to local time, or display the time as entered (which may be
- # confusing since it doesn't show the timezone).
-
def ctime(self):
! "Format a la ctime() in local time."
! t = tmxxx(self.__year, self.__month, self.__day)
! return t.ctime()
def strftime(self, fmt):
! "Format using strftime() in local time."
return _time.strftime(fmt, _time.localtime(self._mktime()))
--- 618,627 ----
# strftime("%c", ...) is locale specific.
def ctime(self):
! "Format a la ctime()."
! return tmxxx(self.__year, self.__month, self.__day).ctime()
def strftime(self, fmt):
! "Format using strftime()."
return _time.strftime(fmt, _time.localtime(self._mktime()))
***************
*** 776,784 ****
Properties (readonly):
! year, month, day, hour, minute, second, microsecond, tzoffset
"""
def __init__(self, year, month, day, hour=0, minute=0, second=0,
! microsecond=0, tzoffset=None):
"""Constructor.
--- 741,749 ----
Properties (readonly):
! year, month, day, hour, minute, second, microsecond
"""
def __init__(self, year, month, day, hour=0, minute=0, second=0,
! microsecond=0):
"""Constructor.
***************
*** 787,792 ****
year, month, day (required, base 1)
hour, minute, second, microsecond (default to zero)
- tzoffset (minutes east of UTC; defaults to local time)
-
"""
super(datetime, self).__init__(year, month, day)
--- 752,755 ----
***************
*** 799,807 ****
if not 0 <= microsecond <= 999999:
raise ValueError('microsecond must be in 0..999999', microsecond)
- if tzoffset is None:
- # XXX Correct, but expensive
- tzoffset = _localtzoffset(year, month, day, hour, minute)
- if not -1439 <= tzoffset <= 1439:
- raise ValueError('tzoffset must be in -1439..1439', tzoffset)
# XXX This duplicates __year, __month, __day for convenience :-(
self.__year = year
--- 762,765 ----
***************
*** 812,816 ****
self.__second = second
self.__microsecond = microsecond
- self.__tzoffset = tzoffset # minutes east of UTC
# Additional constructors
--- 770,773 ----
***************
*** 820,828 ****
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
us = int((t % 1.0) * 1000000)
! if dst > 0:
! tz = -(_time.altzone // 60)
! else:
! tz = -(_time.timezone // 60)
! return cls(y, m, d, hh, mm, ss, us, tz)
fromtimestamp = classmethod(fromtimestamp)
--- 777,781 ----
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
us = int((t % 1.0) * 1000000)
! return cls(y, m, d, hh, mm, ss, us)
fromtimestamp = classmethod(fromtimestamp)
***************
*** 837,841 ****
y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
us = int((t % 1.0) * 1000000)
! return cls(y, m, d, hh, mm, ss, us, 0)
utcfromtimestamp = classmethod(utcfromtimestamp)
--- 790,794 ----
y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
us = int((t % 1.0) * 1000000)
! return cls(y, m, d, hh, mm, ss, us)
utcfromtimestamp = classmethod(utcfromtimestamp)
***************
*** 855,861 ****
del L[-1]
s = ", ".join(map(str, L))
! return "%s(%s, tzoffset=%d)" % (self.__class__.__name__,
! s,
! self.__tzoffset)
def __str__(self):
--- 808,812 ----
del L[-1]
s = ", ".join(map(str, L))
! return "%s(%s)" % (self.__class__.__name__, s)
def __str__(self):
***************
*** 869,874 ****
microsecond = property(lambda self: self.__microsecond,
doc="microsecond (0-999999)")
- tzoffset = property(lambda self: self.__tzoffset,
- doc="time zone offset in minutes east of UTC")
# Standard conversions, __cmp__, __hash__ (and helpers)
--- 820,823 ----
***************
*** 879,883 ****
# Helper to return a POSIX-ish timestamp
t = tmxxx(self.__year, self.__month, self.__day,
! self.__hour, self.__minute - self.__tzoffset, self.__second,
self.__microsecond)
return t.time()
--- 828,832 ----
# Helper to return a POSIX-ish timestamp
t = tmxxx(self.__year, self.__month, self.__day,
! self.__hour, self.__minute, self.__second,
self.__microsecond)
return t.time()
***************
*** 890,923 ****
"Three-way comparison."
if isinstance(other, datetime):
! if self.__tzoffset == other.__tzoffset:
! y, m, d = self.__year, self.__month, self.__day
! H, M = self.__hour, self.__minute
! y2, m2, d2 = other.__year, other.__month, other.__day
! H2, M2 = other.__hour, other.__minute
! else:
! y, m, d, H, M = self._utc_ymdHM()
! y2, m2, d2, H2, M2 = other._utc_ymdHM()
! return cmp((y, m, d, H, M,
! self.__second, self.__microsecond),
! (y2, m2, d2, H2, M2,
! other.__second, other.__microsecond))
! else:
! raise TypeError, ("can't compare datetime to %s instance" %
! type(other).__name__)
!
! def _utc_ymdHM(self):
! # Helper to return (year, month, day, hour, minute) in UTC equivalent
! t = tmxxx(self.__year, self.__month, self.__day,
! self.__hour, self.__minute - self.__tzoffset)
! return t.year, t.month, t.day, t.hour, t.minute
def __hash__(self):
"Hash."
! # Caution: objects that compare equal must have equal hashcodes,
! # and two datetimes can be equal even if their fields aren't
! # (due to tzoffset). So we have to compute a UTC-normalized hash.
! # XXX _utc_ymdHM can be expensive; dream up a quicker correct way.
! y, m, d, H, M = self._utc_ymdHM()
! return hash((y, m, d, H, M, self.__second, self.__microsecond))
# Formatting methods
--- 839,856 ----
"Three-way comparison."
if isinstance(other, datetime):
! return cmp((self.__year, self.__month, self.__day,
! self.__hour, self.__minute, self.__second,
! self.__microsecond),
! (other.__year, other.__month, other.__day,
! other.__hour, other.__minute, other.__second,
! other.__microsecond))
! raise TypeError, ("can't compare datetime to %s instance" %
! type(other).__name__)
def __hash__(self):
"Hash."
! return hash((self.__year, self.__month, self.__day,
! self.__hour, self.__minute, self.__second,
! self.__microsecond))
# Formatting methods
***************
*** 933,959 ****
def ctime(self):
! "Format a la ctime() in local time."
! tzoffset = _localtzoffset(self.__year, self.__month, self.__day, 0, 0)
t = tmxxx(self.__year, self.__month, self.__day, self.__hour,
! self.__minute - self.__tzoffset + tzoffset, self.__second)
! tzoffset1 = _localtzoffset(t.year, t.month, t.day, t.hour, t.minute)
! if tzoffset1 != tzoffset:
! t = tmxxx(t.year, t.month, t.day, t.hour,
! t.minute - tzoffset + tzoffset1, self.__second)
! tzoffset2 = _localtzoffset(t.year, t.month, t.day,
! t.hour, t.minute)
! assert tzoffset2 == tzoffset1 # XXX Hah!
! return t.ctime()
!
! def utcctime(self):
! "Format a la ctime() in UTC."
! t = tmxxx(self.__year, self.__month, self.__day,
! self.__hour, self.__minute - self.__tzoffset, self.__second)
return t.ctime()
- def utcstrftime(self, fmt):
- "Format using strftime() in UTC."
- return _time.strftime(fmt, _time.gmtime(self._mktime()))
-
# Computations
--- 866,874 ----
def ctime(self):
! "Format a la ctime()."
t = tmxxx(self.__year, self.__month, self.__day, self.__hour,
! self.__minute, self.__second)
return t.ctime()
# Computations
***************
*** 971,975 ****
result = self.__class__(t.year, t.month, t.day,
t.hour, t.minute, t.second,
! t.microsecond, self.__tzoffset)
return result
raise TypeError
--- 886,890 ----
result = self.__class__(t.year, t.month, t.day,
t.hour, t.minute, t.second,
! t.microsecond)
return result
raise TypeError
***************
*** 988,996 ****
days1 = self.toordinal()
days2 = other.toordinal()
! secs1 = (self.__second +
! (self.__minute - self.__tzoffset) * 60 +
! self.__hour * 3600)
secs2 = (other.__second +
! (other.__minute - other.__tzoffset) * 60 +
other.__hour * 3600)
return self.timedelta_class(
--- 903,909 ----
days1 = self.toordinal()
days2 = other.toordinal()
! secs1 = (self.__second + self.__minute * 60 + self.__hour * 3600)
secs2 = (other.__second +
! (other.__minute) * 60 +
other.__hour * 3600)
return self.timedelta_class(
***************
*** 1000,1004 ****
return NotImplemented
! # ISO formats including time and tzoffset
def isoformat(self, sep='T'):
--- 913,917 ----
return NotImplemented
! # ISO formats including time
def isoformat(self, sep='T'):
***************
*** 1010,1043 ****
Optional argument sep specifies the separator between date and
time, default 'T'.
-
- This method does not convert to local time.
"""
! if self.__tzoffset >= 0:
! h, m = divmod(self.__tzoffset, 60)
! else:
! h, m = divmod(-self.__tzoffset, 60)
! h = -h
! return "%04d-%02d-%02d%c%02d:%02d:%02d.%06d%+03d:%02d" % (
self.__year, self.__month, self.__day,
sep,
self.__hour, self.__minute, self.__second,
! self.__microsecond,
! h, m)
!
! def utcisoformat(self, sep='T'):
! """Return the time as UTC formatted according to ISO.
!
! This is 'YYYY-MM-DD HH:MM:SS.mmmmmmZ'.
!
! Optional argument sep specifies the separator between date and
! time, default 'T'.
! """
! y, m, d, hh, mm = self._utc_ymdHM()
! return "%04d-%02d-%02d%c%02d:%02d:%02d.%06dZ" % (
! y, m, d, sep, hh, mm, self.__second, self.__microsecond)
! datetime.min = datetime(1, 1, 1, tzoffset=0)
! datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999, tzoffset=0)
datetime.resolution = timedelta(microseconds=1)
--- 923,936 ----
Optional argument sep specifies the separator between date and
time, default 'T'.
"""
! return "%04d-%02d-%02d%c%02d:%02d:%02d.%06d" % (
self.__year, self.__month, self.__day,
sep,
self.__hour, self.__minute, self.__second,
! self.__microsecond)
! datetime.min = datetime(1, 1, 1)
! datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
datetime.resolution = timedelta(microseconds=1)
Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.37
retrieving revision 1.38
diff -C2 -d -r1.37 -r1.38
*** test_datetime.py 5 Mar 2002 14:14:48 -0000 1.37
--- test_datetime.py 6 Mar 2002 01:25:15 -0000 1.38
***************
*** 327,331 ****
def test_roundtrip(self):
! for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7, 8),
self.theclass.now()):
# Verify dt -> string -> datetime identity.
--- 327,331 ----
def test_roundtrip(self):
! for dt in (self.theclass(1, 2, 3, 4, 5, 6, 7),
self.theclass.now()):
# Verify dt -> string -> datetime identity.
***************
*** 337,347 ****
dt2 = self.theclass(dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
! dt.microsecond, dt.tzoffset)
self.assertEqual(dt, dt2)
def test_tz_independent_comparing(self):
! dt1 = self.theclass(2002, 3, 1, 9, 0, 0, tzoffset=-60)
! dt2 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=-60)
! dt3 = self.theclass(2002, 3, 1, 10, 0, 0, tzoffset=0)
self.assertEqual(dt1, dt3)
self.assert_(dt2 > dt3)
--- 337,347 ----
dt2 = self.theclass(dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
! dt.microsecond)
self.assertEqual(dt, dt2)
def test_tz_independent_comparing(self):
! dt1 = self.theclass(2002, 3, 1, 9, 0, 0)
! dt2 = self.theclass(2002, 3, 1, 10, 0, 0)
! dt3 = self.theclass(2002, 3, 1, 9, 0, 0)
self.assertEqual(dt1, dt3)
self.assert_(dt2 > dt3)
***************
*** 352,356 ****
# so comparing via timestamp necessarily calls some distinct values
# equal).
! dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0)
us = timedelta(microseconds=1)
dt2 = dt1 + us
--- 352,356 ----
# so comparing via timestamp necessarily calls some distinct values
# equal).
! dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998)
us = timedelta(microseconds=1)
dt2 = dt1 + us
***************
*** 358,369 ****
self.assert_(dt1 < dt2)
- # Again, but mix timezones.
- dt1 = self.theclass(MAXYEAR, 12, 31, 22, 59, 59, 999998, -60)
- dt2 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998, 0)
- self.assertEqual(dt1, dt2)
- dt2 += us
- self.assertEqual(dt2 - dt1, us)
- self.assert_(dt1 < dt2)
-
def test_bad_constructor_arguments(self):
# bad years
--- 358,361 ----
***************
*** 410,425 ****
2000, 1, 31, 23, 59, 59,
1000000)
- # bad tzoffet
- self.theclass(2, 1, 1, 0, 0, 0, 0, -1439) # no exception
- self.theclass(2, 1, 1, 0, 0, 0, 0, 1439) # no exception
- self.assertRaises(ValueError, self.theclass,
- 2, 1, 1, 0, 0, 0, 0, -1440)
- self.assertRaises(ValueError, self.theclass,
- 2, 1, 1, 0, 0, 0, 0, 1440)
def test_hash_equality(self):
! d = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=-35)
! # same thing in UTC.
! e = self.theclass(2001, 1, 1, 0, 5, 17, tzoffset=0)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
--- 402,409 ----
2000, 1, 31, 23, 59, 59,
1000000)
def test_hash_equality(self):
! d = self.theclass(2000, 12, 31, 23, 30, 17)
! e = self.theclass(2000, 12, 31, 23, 30, 17)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
***************
*** 431,437 ****
self.assertEqual(dic[e], 2)
! d = self.theclass(2001, 1, 1, 0, 5, 17, tzoffset=35)
! # same thing in UTC.
! e = self.theclass(2000, 12, 31, 23, 30, 17, tzoffset=0)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
--- 415,420 ----
self.assertEqual(dic[e], 2)
! d = self.theclass(2001, 1, 1, 0, 5, 17)
! e = self.theclass(2001, 1, 1, 0, 5, 17)
self.assertEqual(d, e)
self.assertEqual(hash(d), hash(e))
***************
*** 498,506 ****
def test_isoformat(self):
! t = self.theclass(2, 3, 2, 4, 5, 1, 123, tzoffset=-120)
! self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123-02:00")
! self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123-02:00")
! self.assertEqual(t.utcisoformat(), "0002-03-02T06:05:01.000123Z")
! self.assertEqual(t.utcisoformat(' '), "0002-03-02 06:05:01.000123Z")
def test_tmxxx(self):
--- 481,488 ----
def test_isoformat(self):
! t = self.theclass(2, 3, 2, 4, 5, 1, 123)
! self.assertEqual(t.isoformat(), "0002-03-02T04:05:01.000123")
! self.assertEqual(t.isoformat('T'), "0002-03-02T04:05:01.000123")
! self.assertEqual(t.isoformat(' '), "0002-03-02 04:05:01.000123")
def test_tmxxx(self):
***************
*** 514,518 ****
(3*60 - 12) * 1000000)
dt2 = self.theclass(tm.year, tm.month, tm.day, tm.hour, tm.minute,
! tm.second, tm.microsecond, tzoffset=0)
self.assertEqual(dt, dt2)
self.assertEqual(timestamp, tm.time())
--- 496,500 ----
(3*60 - 12) * 1000000)
dt2 = self.theclass(tm.year, tm.month, tm.day, tm.hour, tm.minute,
! tm.second, tm.microsecond)
self.assertEqual(dt, dt2)
self.assertEqual(timestamp, tm.time())
***************
*** 521,535 ****
t = self.theclass(2002, 3, 2, 18, 3, 5, 123)
self.assertEqual(t.ctime(), "Sat Mar 2 18:03:05 2002")
- # XXX Can only test utcctime() in known timezone :-(
- # XXX What about the southern hemisphere, where this is DST?
- import time
- if time.timezone == 5*3600:
- self.assertEqual(t.utcctime(), "Sat Mar 2 23:03:05 2002")
- elif time.timezone == 0:
- self.assertEqual(t.utcctime(), "Sat Mar 2 18:03:05 2002")
- elif time.timezone == 3600:
- self.assertEqual(t.utcctime(), "Sat Mar 2 17:03:05 2002")
- else:
- self.fail("Can't test utcctime()")
--- 503,506 ----