PyXR

c:\python24\lib\site-packages\win32\lib \ win32timezone.py



0001 # -*- coding: UTF-8 -*-
0002 
0003 """
0004 win32timezone:
0005         Module for handling datetime.tzinfo time zones using the windows
0006 registry for time zone information.  The time zone names are dependent
0007 on the registry entries defined by the operating system.
0008 
0009         Currently, this module only supports the Windows NT line of products
0010 and not Windows 95/98/Me.
0011 
0012         This module may be tested using the doctest module.
0013 
0014         Written by Jason R. Coombs (jaraco@jaraco.com).
0015         Copyright  2003.
0016         All Rights Reserved.    
0017 
0018         To use this time zone module with the datetime module, simply pass
0019 the TimeZoneInfo object to the datetime constructor.  For example,
0020 
0021 >>> import win32timezone, datetime
0022 >>> assert 'Mountain Standard Time' in win32timezone.GetTimeZoneNames()
0023 >>> tzi = TimeZoneInfo( 'Mountain Standard Time' )
0024 >>> now = datetime.datetime.now( tzi )
0025 
0026         The now object is now a time-zone aware object, and daylight savings-
0027 aware methods may be called on it.
0028 
0029 >>> now.utcoffset() in ( datetime.timedelta(-1, 61200), datetime.timedelta(-1, 64800) )
0030 True
0031 
0032 (note that the result of utcoffset call will be different based on when now was
0033 generated, unless standard time is always used)
0034 
0035 >>> now = datetime.datetime.now( TimeZoneInfo( 'Mountain Standard Time', True ) )
0036 >>> now.utcoffset()
0037 datetime.timedelta(-1, 61200)
0038 
0039 >>> aug2 = datetime.datetime( 2003, 8, 2, tzinfo = tzi )
0040 >>> aug2.utctimetuple()
0041 (2003, 8, 2, 6, 0, 0, 5, 214, 0)
0042 >>> nov2 = datetime.datetime( 2003, 11, 2, tzinfo = tzi )
0043 >>> nov2.utctimetuple()
0044 (2003, 11, 2, 7, 0, 0, 6, 306, 0)
0045 
0046 To convert from one timezone to another, just use the astimezone method.
0047 
0048 >>> aug2.isoformat()
0049 '2003-08-02T00:00:00-06:00'
0050 >>> aug2est = aug2.astimezone( win32timezone.TimeZoneInfo( 'Eastern Standard Time' ) )
0051 >>> aug2est.isoformat()
0052 '2003-08-02T02:00:00-04:00'
0053 
0054 calling the displayName member will return the display name as set in the
0055 registry.
0056 
0057 >>> est = win32timezone.TimeZoneInfo( 'Eastern Standard Time' )
0058 >>> est.displayName
0059 '(GMT-05:00) Eastern Time (US & Canada)'
0060 
0061 >>> gmt = win32timezone.TimeZoneInfo( 'GMT Standard Time', True )
0062 >>> gmt.displayName
0063 '(GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London'
0064 
0065 """
0066 
0067 __author__ = 'Jason R. Coombs <jaraco@jaraco.com>'
0068 __version__ = '$Revision: 1.2 $'[11:-2]
0069 __vssauthor__ = '$Author: mhammond $'[9:-2]
0070 __date__ = '$Modtime: 04-04-14 10:52 $'[10:-2]
0071 
0072 from __future__ import generators
0073 import os, win32api, win32con, struct, datetime
0074 
0075 class TimeZoneInfo( datetime.tzinfo ):
0076         """
0077         Main class for handling win32 time zones.
0078         Usage:
0079                 TimeZoneInfo( <Time Zone Standard Name>, [<Fix Standard Time>] )
0080         If <Fix Standard Time> evaluates to True, daylight savings time is calculated in the same
0081                 way as standard time.
0082         """
0083 
0084         # this key works for WinNT+, but not for the Win95 line.
0085         tzRegKey = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones'
0086                 
0087         def __init__( self, timeZoneName, fixedStandardTime=False ):
0088                 self.timeZoneName = timeZoneName
0089                 tzRegKeyPath = os.path.join( self.tzRegKey, timeZoneName )
0090                 try:
0091                         key = win32api.RegOpenKeyEx( win32con.HKEY_LOCAL_MACHINE,
0092                                                                                  tzRegKeyPath,
0093                                                                                  0,
0094                                                                                  win32con.KEY_READ )
0095                 except:
0096                         raise ValueError, 'Timezone Name %s not found.' % timeZoneName
0097                 self._LoadInfoFromKey( key )
0098                 self.fixedStandardTime = fixedStandardTime
0099 
0100         def _LoadInfoFromKey( self, key ):
0101                 """Loads the information from an opened time zone registry key
0102                 into relevant fields of this TZI object"""
0103                 self.displayName = win32api.RegQueryValueEx( key, "Display" )[0]
0104                 self.standardName = win32api.RegQueryValueEx( key, "Std" )[0]
0105                 self.daylightName = win32api.RegQueryValueEx( key, "Dlt" )[0]
0106                 # TZI contains a structure of time zone information and is similar to
0107                 #  TIME_ZONE_INFORMATION described in the Windows Platform SDK
0108                 winTZI, type = win32api.RegQueryValueEx( key, "TZI" )
0109                 winTZI = struct.unpack( '3l8h8h', winTZI )
0110                 makeMinuteTimeDelta = lambda x: datetime.timedelta( minutes = x )
0111                 self.bias, self.standardBiasOffset, self.daylightBiasOffset = \
0112                                    map( makeMinuteTimeDelta, winTZI[:3] )
0113                 # daylightEnd and daylightStart are 8-tuples representing a Win32 SYSTEMTIME structure
0114                 self.daylightEnd, self.daylightStart = winTZI[3:11], winTZI[11:19]
0115 
0116         def __repr__( self ):
0117                 result = '%s( %s' % ( self.__class__.__name__, repr( self.timeZoneName ) )
0118                 if self.fixedStandardTime:
0119                         result += ', True'
0120                 result += ' )'
0121                 return result
0122 
0123         def __str__( self ):
0124                 return self.displayName
0125 
0126         def tzname( self, dt ):
0127                 if self.dst( dt ) == self.daylightBiasOffset:
0128                         result = self.daylightName
0129                 elif self.dst( dt ) == self.standardBiasOffset:
0130                         result = self.standardName
0131                 return result
0132                 
0133         def _getStandardBias( self ):
0134                 return self.bias + self.standardBiasOffset
0135         standardBias = property( _getStandardBias )
0136 
0137         def _getDaylightBias( self ):
0138                 return self.bias + self.daylightBiasOffset
0139         daylightBias = property( _getDaylightBias )
0140 
0141         def utcoffset( self, dt ):
0142                 "Calculates the utcoffset according to the datetime.tzinfo spec"
0143                 return -( self.bias + self.dst( dt ) )
0144 
0145         def dst( self, dt ):
0146                 "Calculates the daylight savings offset according to the datetime.tzinfo spec"
0147                 assert dt.tzinfo is self
0148                 result = self.standardBiasOffset
0149 
0150                 try:
0151                         dstStart = self.GetDSTStartTime( dt.year )
0152                         dstEnd = self.GetDSTEndTime( dt.year )
0153 
0154                         if dstStart <= dt.replace( tzinfo=None ) < dstEnd and not self.fixedStandardTime:
0155                                 result = self.daylightBiasOffset
0156                 except ValueError:
0157                         # there was an error parsing the time zone, which is normal when a
0158                         #  start and end time are not specified.
0159                         pass
0160 
0161                 return result
0162 
0163         def GetDSTStartTime( self, year ):
0164                 "Given a year, determines the time when daylight savings time starts"
0165                 return self._LocateDay( year, self.daylightStart )
0166 
0167         def GetDSTEndTime( self, year ):
0168                 "Given a year, determines the time when daylight savings ends."
0169                 return self._LocateDay( year, self.daylightEnd )
0170         
0171         def _LocateDay( self, year, win32SystemTime ):
0172                 """
0173                 Takes a SYSTEMTIME structure as retrieved from a TIME_ZONE_INFORMATION
0174                 structure and interprets it based on the given year to identify the actual day.
0175 
0176                 This method is necessary because the SYSTEMTIME structure refers to a day by its
0177                 day of the week or week of the month (e.g. 4th saturday in April).
0178 
0179                 Refer to the Windows Platform SDK for more information on the SYSTEMTIME
0180                 and TIME_ZONE_INFORMATION structures.
0181                 """
0182                 month = win32SystemTime[ 1 ]
0183                 # MS stores Sunday as 0, Python datetime stores Monday as zero
0184                 targetWeekday = ( win32SystemTime[ 2 ] + 6 ) % 7
0185                 # win32SystemTime[3] is the week of the month, so the following
0186                 #  is the first day of that week
0187                 day = ( win32SystemTime[ 3 ] - 1 ) * 7 + 1
0188                 hour, min, sec, msec = win32SystemTime[4:]
0189                 result = datetime.datetime( year, month, day, hour, min, sec, msec )
0190                 # now the result is the correct week, but not necessarily the correct day of the week
0191                 daysToGo = targetWeekday - result.weekday()
0192                 result += datetime.timedelta( daysToGo )
0193                 # if we selected a day in the month following the target month,
0194                 #  move back a week or two.
0195                 # This is necessary because Microsoft defines the fifth week in a month
0196                 #  to be the last week in a month and adding the time delta might have
0197                 #  pushed the result into the next month.
0198                 while result.month == month + 1:
0199                         result -= datetime.timedelta( weeks = 1 )
0200                 return result
0201 
0202 def _RegKeyEnumerator( key ):
0203         "Enumerates an open registry key as an iterable generator"
0204         index = 0
0205         try:
0206                 while 1:
0207                         yield win32api.RegEnumKey( key, index )
0208                         index += 1
0209         except win32api.error: pass
0210 
0211 def GetTimeZoneNames( ):
0212         "Returns the names of the time zones as defined in the registry"
0213         key = win32api.RegOpenKeyEx( win32con.HKEY_LOCAL_MACHINE,
0214                                                                  TimeZoneInfo.tzRegKey,
0215                                                                  0,
0216                                                                  win32con.KEY_READ )
0217         return _RegKeyEnumerator( key )
0218 
0219 def GetIndexedTimeZoneNames( ):
0220         """Returns the names of the time zones as defined in the registry, but includes
0221         the index by which they may be sorted longitudinally."""
0222         for timeZoneName in GetTimeZoneNames():
0223                 tzRegKeyPath = os.path.join( TimeZoneInfo.tzRegKey, timeZoneName )
0224                 key = win32api.RegOpenKeyEx( win32con.HKEY_LOCAL_MACHINE,
0225                                                                          tzRegKeyPath,
0226                                                                          0,
0227                                                                          win32con.KEY_READ )
0228                 tzIndex, type = win32api.RegQueryValueEx( key, 'Index' )
0229                 yield ( tzIndex, timeZoneName )
0230 
0231 def GetSortedTimeZoneNames( ):
0232         """ Uses GetIndexedTimeZoneNames to return the time zone names sorted
0233         longitudinally."""
0234         tzs = list( GetIndexedTimeZoneNames() )
0235         tzs.sort()
0236         return zip( *tzs )[1]
0237 
0238 def GetLocalTimeZone( ):
0239         """Returns the local time zone as defined by the operating system in the registry
0240         >>> localTZ = GetLocalTimeZone()
0241         >>> nowLoc = datetime.datetime.now( localTZ )
0242         >>> nowUTC = datetime.datetime.utcnow( )
0243         >>> ( nowUTC - nowLoc ) < datetime.timedelta( seconds = 5 )
0244         Traceback (most recent call last):
0245           ...
0246         TypeError: can't subtract offset-naive and offset-aware datetimes
0247 
0248         >>> nowUTC = nowUTC.replace( tzinfo = TimeZoneInfo( 'GMT Standard Time', True ) )
0249 
0250         Now one can compare the results of the two offset aware values  
0251         >>> ( nowUTC - nowLoc ) < datetime.timedelta( seconds = 5 )
0252         True
0253         """
0254         tzRegKey = r'SYSTEM\CurrentControlSet\Control\TimeZoneInformation'
0255         key = win32api.RegOpenKeyEx( win32con.HKEY_LOCAL_MACHINE,
0256                                                                  tzRegKey,
0257                                                                  0,
0258                                                                  win32con.KEY_READ )
0259         tzName, type = win32api.RegQueryValueEx( key, 'StandardName' )
0260         return TimeZoneInfo( tzName )
0261 

Generated by PyXR 0.9.4
SourceForge.net Logo