Back to index

python3.2  3.2.2
Public Member Functions | Static Public Attributes
test.datetimetester.TestTimezoneConversions Class Reference

List of all members.

Public Member Functions

def checkinside
def checkoutside
def convert_between_tz_and_utc
def test_easy
def test_tricky
def test_bogus_dst
def test_fromutc

Static Public Attributes

tuple dston = datetime(2002, 4, 7, 2)
tuple dstoff = datetime(2002, 10, 27, 1)
 theclass = datetime

Detailed Description

Definition at line 3383 of file datetimetester.py.


Member Function Documentation

def test.datetimetester.TestTimezoneConversions.checkinside (   self,
  dt,
  tz,
  utc,
  dston,
  dstoff 
)

Definition at line 3391 of file datetimetester.py.

03391 
03392     def checkinside(self, dt, tz, utc, dston, dstoff):
03393         self.assertEqual(dt.dst(), HOUR)
03394 
03395         # Conversion to our own timezone is always an identity.
03396         self.assertEqual(dt.astimezone(tz), dt)
03397 
03398         asutc = dt.astimezone(utc)
03399         there_and_back = asutc.astimezone(tz)
03400 
03401         # Conversion to UTC and back isn't always an identity here,
03402         # because there are redundant spellings (in local time) of
03403         # UTC time when DST begins:  the clock jumps from 1:59:59
03404         # to 3:00:00, and a local time of 2:MM:SS doesn't really
03405         # make sense then.  The classes above treat 2:MM:SS as
03406         # daylight time then (it's "after 2am"), really an alias
03407         # for 1:MM:SS standard time.  The latter form is what
03408         # conversion back from UTC produces.
03409         if dt.date() == dston.date() and dt.hour == 2:
03410             # We're in the redundant hour, and coming back from
03411             # UTC gives the 1:MM:SS standard-time spelling.
03412             self.assertEqual(there_and_back + HOUR, dt)
03413             # Although during was considered to be in daylight
03414             # time, there_and_back is not.
03415             self.assertEqual(there_and_back.dst(), ZERO)
03416             # They're the same times in UTC.
03417             self.assertEqual(there_and_back.astimezone(utc),
03418                              dt.astimezone(utc))
03419         else:
03420             # We're not in the redundant hour.
03421             self.assertEqual(dt, there_and_back)
03422 
03423         # Because we have a redundant spelling when DST begins, there is
03424         # (unfortunately) an hour when DST ends that can't be spelled at all in
03425         # local time.  When DST ends, the clock jumps from 1:59 back to 1:00
03426         # again.  The hour 1:MM DST has no spelling then:  1:MM is taken to be
03427         # standard time.  1:MM DST == 0:MM EST, but 0:MM is taken to be
03428         # daylight time.  The hour 1:MM daylight == 0:MM standard can't be
03429         # expressed in local time.  Nevertheless, we want conversion back
03430         # from UTC to mimic the local clock's "repeat an hour" behavior.
03431         nexthour_utc = asutc + HOUR
03432         nexthour_tz = nexthour_utc.astimezone(tz)
03433         if dt.date() == dstoff.date() and dt.hour == 0:
03434             # We're in the hour before the last DST hour.  The last DST hour
03435             # is ineffable.  We want the conversion back to repeat 1:MM.
03436             self.assertEqual(nexthour_tz, dt.replace(hour=1))
03437             nexthour_utc += HOUR
03438             nexthour_tz = nexthour_utc.astimezone(tz)
03439             self.assertEqual(nexthour_tz, dt.replace(hour=1))
03440         else:
03441             self.assertEqual(nexthour_tz - dt, HOUR)

Here is the call graph for this function:

Here is the caller graph for this function:

def test.datetimetester.TestTimezoneConversions.checkoutside (   self,
  dt,
  tz,
  utc 
)

Definition at line 3443 of file datetimetester.py.

03443 
03444     def checkoutside(self, dt, tz, utc):
03445         self.assertEqual(dt.dst(), ZERO)
03446 
03447         # Conversion to our own timezone is always an identity.
03448         self.assertEqual(dt.astimezone(tz), dt)
03449 
03450         # Converting to UTC and back is an identity too.
03451         asutc = dt.astimezone(utc)
03452         there_and_back = asutc.astimezone(tz)
03453         self.assertEqual(dt, there_and_back)

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3454 of file datetimetester.py.

03454 
03455     def convert_between_tz_and_utc(self, tz, utc):
03456         dston = self.dston.replace(tzinfo=tz)
03457         # Because 1:MM on the day DST ends is taken as being standard time,
03458         # there is no spelling in tz for the last hour of daylight time.
03459         # For purposes of the test, the last hour of DST is 0:MM, which is
03460         # taken as being daylight time (and 1:MM is taken as being standard
03461         # time).
03462         dstoff = self.dstoff.replace(tzinfo=tz)
03463         for delta in (timedelta(weeks=13),
03464                       DAY,
03465                       HOUR,
03466                       timedelta(minutes=1),
03467                       timedelta(microseconds=1)):
03468 
03469             self.checkinside(dston, tz, utc, dston, dstoff)
03470             for during in dston + delta, dstoff - delta:
03471                 self.checkinside(during, tz, utc, dston, dstoff)
03472 
03473             self.checkoutside(dstoff, tz, utc)
03474             for outside in dston - delta, dstoff + delta:
03475                 self.checkoutside(outside, tz, utc)

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3551 of file datetimetester.py.

03551 
03552     def test_bogus_dst(self):
03553         class ok(tzinfo):
03554             def utcoffset(self, dt): return HOUR
03555             def dst(self, dt): return HOUR
03556 
03557         now = self.theclass.now().replace(tzinfo=utc_real)
03558         # Doesn't blow up.
03559         now.astimezone(ok())
03560 
03561         # Does blow up.
03562         class notok(ok):
03563             def dst(self, dt): return None
03564         self.assertRaises(ValueError, now.astimezone, notok())
03565 
03566         # Sometimes blow up. In the following, tzinfo.dst()
03567         # implementation may return None or not None depending on
03568         # whether DST is assumed to be in effect.  In this situation,
03569         # a ValueError should be raised by astimezone().
03570         class tricky_notok(ok):
03571             def dst(self, dt):
03572                 if dt.year == 2000:
03573                     return None
03574                 else:
03575                     return 10*HOUR
03576         dt = self.theclass(2001, 1, 1).replace(tzinfo=utc_real)
03577         self.assertRaises(ValueError, dt.astimezone, tricky_notok())

Here is the call graph for this function:

Definition at line 3476 of file datetimetester.py.

03476 
03477     def test_easy(self):
03478         # Despite the name of this test, the endcases are excruciating.
03479         self.convert_between_tz_and_utc(Eastern, utc_real)
03480         self.convert_between_tz_and_utc(Pacific, utc_real)
03481         self.convert_between_tz_and_utc(Eastern, utc_fake)
03482         self.convert_between_tz_and_utc(Pacific, utc_fake)
03483         # The next is really dancing near the edge.  It works because
03484         # Pacific and Eastern are far enough apart that their "problem
03485         # hours" don't overlap.
03486         self.convert_between_tz_and_utc(Eastern, Pacific)
03487         self.convert_between_tz_and_utc(Pacific, Eastern)
03488         # OTOH, these fail!  Don't enable them.  The difficulty is that
03489         # the edge case tests assume that every hour is representable in
03490         # the "utc" class.  This is always true for a fixed-offset tzinfo
03491         # class (lke utc_real and utc_fake), but not for Eastern or Central.
03492         # For these adjacent DST-aware time zones, the range of time offsets
03493         # tested ends up creating hours in the one that aren't representable
03494         # in the other.  For the same reason, we would see failures in the
03495         # Eastern vs Pacific tests too if we added 3*HOUR to the list of
03496         # offset deltas in convert_between_tz_and_utc().
03497         #
03498         # self.convert_between_tz_and_utc(Eastern, Central)  # can't work
03499         # self.convert_between_tz_and_utc(Central, Eastern)  # can't work

Here is the call graph for this function:

Definition at line 3578 of file datetimetester.py.

03578 
03579     def test_fromutc(self):
03580         self.assertRaises(TypeError, Eastern.fromutc)   # not enough args
03581         now = datetime.utcnow().replace(tzinfo=utc_real)
03582         self.assertRaises(ValueError, Eastern.fromutc, now) # wrong tzinfo
03583         now = now.replace(tzinfo=Eastern)   # insert correct tzinfo
03584         enow = Eastern.fromutc(now)         # doesn't blow up
03585         self.assertEqual(enow.tzinfo, Eastern) # has right tzinfo member
03586         self.assertRaises(TypeError, Eastern.fromutc, now, now) # too many args
03587         self.assertRaises(TypeError, Eastern.fromutc, date.today()) # wrong type
03588 
03589         # Always converts UTC to standard time.
03590         class FauxUSTimeZone(USTimeZone):
03591             def fromutc(self, dt):
03592                 return dt + self.stdoffset
03593         FEastern  = FauxUSTimeZone(-5, "FEastern",  "FEST", "FEDT")
03594 
03595         #  UTC  4:MM  5:MM  6:MM  7:MM  8:MM  9:MM
03596         #  EST 23:MM  0:MM  1:MM  2:MM  3:MM  4:MM
03597         #  EDT  0:MM  1:MM  2:MM  3:MM  4:MM  5:MM
03598 
03599         # Check around DST start.
03600         start = self.dston.replace(hour=4, tzinfo=Eastern)
03601         fstart = start.replace(tzinfo=FEastern)
03602         for wall in 23, 0, 1, 3, 4, 5:
03603             expected = start.replace(hour=wall)
03604             if wall == 23:
03605                 expected -= timedelta(days=1)
03606             got = Eastern.fromutc(start)
03607             self.assertEqual(expected, got)
03608 
03609             expected = fstart + FEastern.stdoffset
03610             got = FEastern.fromutc(fstart)
03611             self.assertEqual(expected, got)
03612 
03613             # Ensure astimezone() calls fromutc() too.
03614             got = fstart.replace(tzinfo=utc_real).astimezone(FEastern)
03615             self.assertEqual(expected, got)
03616 
03617             start += HOUR
03618             fstart += HOUR
03619 
03620         # Check around DST end.
03621         start = self.dstoff.replace(hour=4, tzinfo=Eastern)
03622         fstart = start.replace(tzinfo=FEastern)
03623         for wall in 0, 1, 1, 2, 3, 4:
03624             expected = start.replace(hour=wall)
03625             got = Eastern.fromutc(start)
03626             self.assertEqual(expected, got)
03627 
03628             expected = fstart + FEastern.stdoffset
03629             got = FEastern.fromutc(fstart)
03630             self.assertEqual(expected, got)
03631 
03632             # Ensure astimezone() calls fromutc() too.
03633             got = fstart.replace(tzinfo=utc_real).astimezone(FEastern)
03634             self.assertEqual(expected, got)
03635 
03636             start += HOUR
03637             fstart += HOUR
03638 

Here is the call graph for this function:

Definition at line 3500 of file datetimetester.py.

03500 
03501     def test_tricky(self):
03502         # 22:00 on day before daylight starts.
03503         fourback = self.dston - timedelta(hours=4)
03504         ninewest = FixedOffset(-9*60, "-0900", 0)
03505         fourback = fourback.replace(tzinfo=ninewest)
03506         # 22:00-0900 is 7:00 UTC == 2:00 EST == 3:00 DST.  Since it's "after
03507         # 2", we should get the 3 spelling.
03508         # If we plug 22:00 the day before into Eastern, it "looks like std
03509         # time", so its offset is returned as -5, and -5 - -9 = 4.  Adding 4
03510         # to 22:00 lands on 2:00, which makes no sense in local time (the
03511         # local clock jumps from 1 to 3).  The point here is to make sure we
03512         # get the 3 spelling.
03513         expected = self.dston.replace(hour=3)
03514         got = fourback.astimezone(Eastern).replace(tzinfo=None)
03515         self.assertEqual(expected, got)
03516 
03517         # Similar, but map to 6:00 UTC == 1:00 EST == 2:00 DST.  In that
03518         # case we want the 1:00 spelling.
03519         sixutc = self.dston.replace(hour=6, tzinfo=utc_real)
03520         # Now 6:00 "looks like daylight", so the offset wrt Eastern is -4,
03521         # and adding -4-0 == -4 gives the 2:00 spelling.  We want the 1:00 EST
03522         # spelling.
03523         expected = self.dston.replace(hour=1)
03524         got = sixutc.astimezone(Eastern).replace(tzinfo=None)
03525         self.assertEqual(expected, got)
03526 
03527         # Now on the day DST ends, we want "repeat an hour" behavior.
03528         #  UTC  4:MM  5:MM  6:MM  7:MM  checking these
03529         #  EST 23:MM  0:MM  1:MM  2:MM
03530         #  EDT  0:MM  1:MM  2:MM  3:MM
03531         # wall  0:MM  1:MM  1:MM  2:MM  against these
03532         for utc in utc_real, utc_fake:
03533             for tz in Eastern, Pacific:
03534                 first_std_hour = self.dstoff - timedelta(hours=2) # 23:MM
03535                 # Convert that to UTC.
03536                 first_std_hour -= tz.utcoffset(None)
03537                 # Adjust for possibly fake UTC.
03538                 asutc = first_std_hour + utc.utcoffset(None)
03539                 # First UTC hour to convert; this is 4:00 when utc=utc_real &
03540                 # tz=Eastern.
03541                 asutcbase = asutc.replace(tzinfo=utc)
03542                 for tzhour in (0, 1, 1, 2):
03543                     expectedbase = self.dstoff.replace(hour=tzhour)
03544                     for minute in 0, 30, 59:
03545                         expected = expectedbase.replace(minute=minute)
03546                         asutc = asutcbase.replace(minute=minute)
03547                         astz = asutc.astimezone(tz)
03548                         self.assertEqual(astz.replace(tzinfo=None), expected)
03549                     asutcbase += HOUR
03550 

Here is the call graph for this function:


Member Data Documentation

Definition at line 3386 of file datetimetester.py.

Definition at line 3385 of file datetimetester.py.

Definition at line 3388 of file datetimetester.py.


The documentation for this class was generated from the following file: