[pywin32-checkins] /hgroot/pywin32/pywin32: 4 new changesets
OLD project page for the Python extensions for Windows
Brought to you by:
mhammond
From: <pyw...@li...> - 2012-05-10 13:12:47
|
changeset f3b7d2b5ea18 in /hgroot/pywin32/pywin32 details: http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/hgroot/pywin32/pywin32?cmd=changeset;node=f3b7d2b5ea18 summary: Added test capturing failure indicated by #3524786. changeset dbb2d86a9bbc in /hgroot/pywin32/pywin32 details: http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/hgroot/pywin32/pywin32?cmd=changeset;node=dbb2d86a9bbc summary: Potential fix for 3524786 changeset ba623bb65a7b in /hgroot/pywin32/pywin32 details: http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/hgroot/pywin32/pywin32?cmd=changeset;node=ba623bb65a7b summary: 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. changeset 70123c669c9e in /hgroot/pywin32/pywin32 details: http://pywin32.hg.sourceforge.net/hgweb/pywin32/pywin32/hgroot/pywin32/pywin32?cmd=changeset;node=70123c669c9e summary: collapse tag fix diffstat: .hgtags | 94 +++++++++++++++++++++++----------------------- win32/Lib/win32timezone.py | 65 +++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 51 deletions(-) diffs (215 lines): diff -r 085048997feb -r 70123c669c9e .hgtags --- a/.hgtags Fri May 04 20:11:44 2012 -0400 +++ b/.hgtags Thu May 10 09:09:42 2012 -0400 @@ -1,48 +1,48 @@ -41f1bd66b7021c117875e6b682c497ed6fc2cc10 b206 -3f840c6cf56d1cebf71f6431a4e0efbdfdbad67f b207 -f661faf30bc176e8c7da0f270cacc6efeec6f93b b200 -3cc78fc452fc36735ad7657d55ada4a8c707ce98 b201 -e9680446f9501cea73d8c7cbb4f605ac4735f9f7 b134 -21b963e6aef75c4200cffad4e1d82f00ea7f4004 b135 -5772e8f5879d4e99bd8f011ebd6e22ac77b62326 b132 -cfc3d45d90b99ba94f2a4f0959bc87929c6bd467 b205 -509f3e5d7cf8a3538107fd16f0082c2cbfc6969b b130 -1c7f25ac9159234948ab5b6dc90bbb4a40cdb004 b131 -18e90fae54ee83cd4e843eea420363238310bad7 b208 -66090658b3de364fc0c82f8ba50c8e53c6656c31 b209 -fc11455ae6b156ef2f5de8c9278249ca331f62d0 py3k-merge-complete -be3f97064797e0ca0cd74e9eaa87165e10f7cad1 ActivePython210 -dc1672d20522850fae56111e22ccb5685f42f595 ActivePython211 -4273326c4e0d7bf084a6f9b2053d932e22a931be b157 -c29a3a48e23333cf69bf06e38709fb95dc1c4e0b b151 -84e9214951e2e643b4cc69f3aeb65096a9084333 b153 -627797aca18f5da4f850d1ce7a3b92551a00d9dc b159 -4381189ca772314be36c8f3ab6405df2b0e3054c b214 -6c8737a7ad24df7221bb5185454b9eea9ace1e43 b139 -78f2b0c832f605e114e054428b0c7cbb5b604b3f adodbapi_2_1 -0059bca6a08fd0f53ed15c53dd9c7cdf4f30277a b213 -e2bf22f83e33af157d585b97c84396a9e29517e2 b212 -2d64b7bd69085ff1a205082a342ceaa901b315db b211 -0368e8bf35fe715afdc8cd4e0f14207395d57b0f a2 -a9c6f2e0d1c9abe01912609898571aa392b872c7 b216 -3ed66b823bbf0deb92a34c86dd1dd6814bb48c5e b127 -389edbdcad88a68b57d3d4a75bc86c8804cf49c0 b126 -cc382129d3bedf1392fbb44b9ded529ff6b4de0e b129 -b64d19fa71db1cbc33c29d6ba5b4941beae80c8e b128 -9f6fdae45eb75468d6c09c77782219879c4c50bf b215 -06b7c2aead8d38bb7364b4efbdff51e5afb7f839 b147 -bdd4dbfaa9bc4b4758a912daeb8d30c3ec12d081 b146 -9dbc9b744bd27066f74d9c09da70866d99fe71f7 b145 -81514808c099a0060e5318b7e5dc1c53c6ebb3ab ActivePython202 -7900668f7ffb11e819e1a3ae8755f86c89552fcd b142 -917d31f81f0044a01c2c3516e2cf080a33206f97 b141 -1a192704d03f2c0b9cd0fb7fa59b6df51b696973 b140 -59e2f06b53e4d3ea81109e76bd686677d34d21f4 adodbapi_2_2_2 -972b58e9f118695958deebe404726e4f957f0e8b b202 -54c1f0e5035e1bd2cd38761b830778f91fd0f1d0 b149 -f21d815cbde468897d74c4f9c4de09ab8306c405 b148 -a8e244f6bb667d07c1d4b4ad1e163f3a99f7eaae b203 -b634f1c59fb9b502d2c1ee9e692e4067d7940901 b129f -c3eb7ad6c64194e120ad9037fa6299b7c6a6ef1e b204 -6ccccc93a646531a4fb0d904b83e18d324c59d01 cvs2hg +41f1bd66b7021c117875e6b682c497ed6fc2cc10 b206 +3f840c6cf56d1cebf71f6431a4e0efbdfdbad67f b207 +f661faf30bc176e8c7da0f270cacc6efeec6f93b b200 +3cc78fc452fc36735ad7657d55ada4a8c707ce98 b201 +e9680446f9501cea73d8c7cbb4f605ac4735f9f7 b134 +21b963e6aef75c4200cffad4e1d82f00ea7f4004 b135 +5772e8f5879d4e99bd8f011ebd6e22ac77b62326 b132 +cfc3d45d90b99ba94f2a4f0959bc87929c6bd467 b205 +509f3e5d7cf8a3538107fd16f0082c2cbfc6969b b130 +1c7f25ac9159234948ab5b6dc90bbb4a40cdb004 b131 +18e90fae54ee83cd4e843eea420363238310bad7 b208 +66090658b3de364fc0c82f8ba50c8e53c6656c31 b209 +fc11455ae6b156ef2f5de8c9278249ca331f62d0 py3k-merge-complete +be3f97064797e0ca0cd74e9eaa87165e10f7cad1 ActivePython210 +dc1672d20522850fae56111e22ccb5685f42f595 ActivePython211 +4273326c4e0d7bf084a6f9b2053d932e22a931be b157 +c29a3a48e23333cf69bf06e38709fb95dc1c4e0b b151 +84e9214951e2e643b4cc69f3aeb65096a9084333 b153 +627797aca18f5da4f850d1ce7a3b92551a00d9dc b159 +4381189ca772314be36c8f3ab6405df2b0e3054c b214 +6c8737a7ad24df7221bb5185454b9eea9ace1e43 b139 +78f2b0c832f605e114e054428b0c7cbb5b604b3f adodbapi_2_1 +0059bca6a08fd0f53ed15c53dd9c7cdf4f30277a b213 +e2bf22f83e33af157d585b97c84396a9e29517e2 b212 +2d64b7bd69085ff1a205082a342ceaa901b315db b211 +0368e8bf35fe715afdc8cd4e0f14207395d57b0f a2 +a9c6f2e0d1c9abe01912609898571aa392b872c7 b216 +3ed66b823bbf0deb92a34c86dd1dd6814bb48c5e b127 +389edbdcad88a68b57d3d4a75bc86c8804cf49c0 b126 +cc382129d3bedf1392fbb44b9ded529ff6b4de0e b129 +b64d19fa71db1cbc33c29d6ba5b4941beae80c8e b128 +9f6fdae45eb75468d6c09c77782219879c4c50bf b215 +06b7c2aead8d38bb7364b4efbdff51e5afb7f839 b147 +bdd4dbfaa9bc4b4758a912daeb8d30c3ec12d081 b146 +9dbc9b744bd27066f74d9c09da70866d99fe71f7 b145 +81514808c099a0060e5318b7e5dc1c53c6ebb3ab ActivePython202 +7900668f7ffb11e819e1a3ae8755f86c89552fcd b142 +917d31f81f0044a01c2c3516e2cf080a33206f97 b141 +1a192704d03f2c0b9cd0fb7fa59b6df51b696973 b140 +59e2f06b53e4d3ea81109e76bd686677d34d21f4 adodbapi_2_2_2 +972b58e9f118695958deebe404726e4f957f0e8b b202 +54c1f0e5035e1bd2cd38761b830778f91fd0f1d0 b149 +f21d815cbde468897d74c4f9c4de09ab8306c405 b148 +a8e244f6bb667d07c1d4b4ad1e163f3a99f7eaae b203 +b634f1c59fb9b502d2c1ee9e692e4067d7940901 b129f +c3eb7ad6c64194e120ad9037fa6299b7c6a6ef1e b204 +6ccccc93a646531a4fb0d904b83e18d324c59d01 cvs2hg 5c3a57938569a9a0321b59037bddf99721f61f95 b217 diff -r 085048997feb -r 70123c669c9e win32/Lib/win32timezone.py --- a/win32/Lib/win32timezone.py Fri May 04 20:11:44 2012 -0400 +++ b/win32/Lib/win32timezone.py Thu May 10 09:09:42 2012 -0400 @@ -202,6 +202,8 @@ 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) @@ -223,7 +225,32 @@ True >>> (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 <ja...@ja...>' @@ -588,6 +615,19 @@ 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 @@ -605,22 +645,36 @@ return -result def _inDaylightSavings(self, dt): + dt = dt.replace(tzinfo=None) + winInfo = self.getWinInfo(dt.year) try: dstStart = self.GetDSTStartTime(dt.year) dstEnd = self.GetDSTEndTime(dt.year) + # at the end of DST, when clocks are moved back, there's a period + # of daylight_bias where it's ambiguous whether we're in DST or + # not. + dstEndAdj = dstEnd + winInfo.daylight_bias + + # the same thing could theoretically happen at the start of DST + # 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: - inDaylightSavings = dstStart <= dt.replace(tzinfo=None) < dstEnd + in_dst = dstStartAdj <= dt < dstEndAdj else: # in the southern hemisphere, daylight savings time # typically ends before it begins in a given year. - inDaylightSavings = not (dstEnd < dt.replace(tzinfo=None) <= dstStart) + in_dst = not (dstEndAdj < dt <= dstStartAdj) except ValueError: # there was an error parsing the time zone, which is normal when a # start and end time are not specified. - inDaylightSavings = False + in_dst = False - return inDaylightSavings + return in_dst def GetDSTStartTime(self, year): "Given a year, determines the time when daylight savings time starts" @@ -787,6 +841,9 @@ 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 |