Commits

Jason R. Coombs committed ba623bb

win32timezone now recognizes when attempts to discern dst are ambiguous and raises win32timezone.AmbiguousTimeError in that case. This change required overriding fromutc because the default implementation depends on the dst-shifted times and cannot use the standard bias directly.

Comments (0)

Files changed (1)

win32/Lib/win32timezone.py

 datetime.datetime(2011, 11, 5, 19, 0, tzinfo=TimeZoneInfo('Pacific Standard Time'))
 
 Make sure the converted time is correct.
+>>> tz_pac
+TimeZoneInfo('Pacific Standard Time')
 >>> dt_pac = dt_hi.astimezone(tz_pac)
 >>> dt_pac.timetuple()
 time.struct_time(tm_year=2011, tm_mon=11, tm_mday=5, tm_hour=19, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=309, tm_isdst=1)
 >>> (offset + dst_offset) == datetime.timedelta(hours=-7)
 True
 
-
 Test offsets that occur right at the DST changeover
 >>> datetime.datetime.utcfromtimestamp(1320570000).replace(
 ...     tzinfo=TimeZoneInfo.utc()).astimezone(tz_pac)
 datetime.datetime(2011, 11, 6, 1, 0, tzinfo=TimeZoneInfo('Pacific Standard Time'))
 
+TimeZoneInfo now raises AmbiguousTimeError for ambiguous times
+==============================================================
+
+Is 1:15 the first one, or the one after clocks were set back?
+>>> ambiguous = datetime.datetime(2011, 11, 6, 1, 15)
+>>> est = TimeZoneInfo('Eastern Standard Time')
+>>> est.dst(ambiguous)
+Traceback (most recent call last):
+[...]
+AmbiguousTimeError: 2011-11-06 01:15:00
+>>> est.utcoffset(ambiguous)
+Traceback (most recent call last):
+[...]
+AmbiguousTimeError: 2011-11-06 01:15:00
+
+However, if we're converting from UTC, it's not ambiguous.
+>>> datetime.datetime(2011, 11, 6, 6, 0, tzinfo=TimeZoneInfo.utc()).astimezone(est)
+datetime.datetime(2011, 11, 6, 1, 0, tzinfo=TimeZoneInfo('Eastern Standard Time'))
 """
+
 from __future__ import generators
 
 __author__ = 'Jason R. Coombs <jaraco@jaraco.com>'
 		winInfo = self.getWinInfo(dt.year)
 		return winInfo.bias + winInfo.daylight_bias
 
+	def fromutc(self, dt):
+		if dt.tzinfo is not self:
+			raise ValueError("tzinfo is not self")
+		# calculate the local time using the standard offset
+		tz_std = TimeZoneInfo(self.timeZoneName, fix_standard_time=True)
+		delta = tz_std.utcoffset(dt)
+		dt += delta
+		try:
+			dt += self.dst(dt)
+		except AmbiguousTimeError:
+			pass
+		return dt
+
 	def utcoffset(self, dt):
 		"Calculates the utcoffset according to the datetime.tzinfo spec"
 		if dt is None: return
 			#  if there's a standard_bias (which I suspect is always 0).
 			dstStartAdj = dstStart + winInfo.standard_bias
 
+			if dstEndAdj <= dt < dstEnd or dstStartAdj <= dt < dstStart:
+				raise AmbiguousTimeError(dt)
+
 			if dstStart < dstEnd:
 				in_dst = dstStartAdj <= dt < dstEndAdj
 			else:
 GetSortedTimeZoneNames = deprecated(TimeZoneInfo.get_sorted_time_zone_names, 'GetSortedTimeZoneNames')
 # end backward compatibility
 
+class AmbiguousTimeError(Exception):
+	pass
+
 def utcnow():
 	"""
 	Return the UTC time now with timezone awareness as enabled