Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

163 linhas
5.6 KiB

  1. import _winreg
  2. import struct
  3. import datetime
  4. handle = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
  5. tzparent = _winreg.OpenKey(handle,
  6. "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones")
  7. parentsize = _winreg.QueryInfoKey(tzparent)[0]
  8. localkey = _winreg.OpenKey(handle,
  9. "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation")
  10. WEEKS = datetime.timedelta(7)
  11. def list_timezones():
  12. """Return a list of all time zones known to the system."""
  13. l = []
  14. for i in xrange(parentsize):
  15. l.append(_winreg.EnumKey(tzparent, i))
  16. return l
  17. class win32tz(datetime.tzinfo):
  18. """tzinfo class based on win32's timezones available in the registry.
  19. >>> local = win32tz('Central Standard Time')
  20. >>> oct1 = datetime.datetime(month=10, year=2004, day=1, tzinfo=local)
  21. >>> dec1 = datetime.datetime(month=12, year=2004, day=1, tzinfo=local)
  22. >>> oct1.dst()
  23. datetime.timedelta(0, 3600)
  24. >>> dec1.dst()
  25. datetime.timedelta(0)
  26. >>> braz = win32tz('E. South America Standard Time')
  27. >>> braz.dst(oct1)
  28. datetime.timedelta(0)
  29. >>> braz.dst(dec1)
  30. datetime.timedelta(0, 3600)
  31. """
  32. def __init__(self, name):
  33. self.data = win32tz_data(name)
  34. def utcoffset(self, dt):
  35. if self._isdst(dt):
  36. return datetime.timedelta(minutes=self.data.dstoffset)
  37. else:
  38. return datetime.timedelta(minutes=self.data.stdoffset)
  39. def dst(self, dt):
  40. if self._isdst(dt):
  41. minutes = self.data.dstoffset - self.data.stdoffset
  42. return datetime.timedelta(minutes=minutes)
  43. else:
  44. return datetime.timedelta(0)
  45. def tzname(self, dt):
  46. if self._isdst(dt):
  47. return self.data.dstname
  48. else:
  49. return self.data.stdname
  50. def _isdst(self, dt):
  51. dat = self.data
  52. dston = pickNthWeekday(dt.year, dat.dstmonth, dat.dstdayofweek,
  53. dat.dsthour, dat.dstminute, dat.dstweeknumber)
  54. dstoff = pickNthWeekday(dt.year, dat.stdmonth, dat.stddayofweek,
  55. dat.stdhour, dat.stdminute, dat.stdweeknumber)
  56. if dston < dstoff:
  57. return (dston <= dt.replace(tzinfo=None) < dstoff)
  58. else:
  59. return not (dstoff <= dt.replace(tzinfo=None) < dston)
  60. def __repr__(self):
  61. return "<win32tz - {0!s}>".format(self.data.display)
  62. def pickNthWeekday(year, month, dayofweek, hour, minute, whichweek):
  63. """dayofweek == 0 means Sunday, whichweek > 4 means last instance"""
  64. first = datetime.datetime(year=year, month=month, hour=hour, minute=minute,
  65. day=1)
  66. weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7 + 1))
  67. for n in xrange(whichweek - 1, -1, -1):
  68. dt = weekdayone + n * WEEKS
  69. if dt.month == month:
  70. return dt
  71. class win32tz_data(object):
  72. """Read a registry key for a timezone, expose its contents."""
  73. def __init__(self, path):
  74. """Load path, or if path is empty, load local time."""
  75. if path:
  76. keydict = valuesToDict(_winreg.OpenKey(tzparent, path))
  77. self.display = keydict['Display']
  78. self.dstname = keydict['Dlt']
  79. self.stdname = keydict['Std']
  80. #see http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
  81. tup = struct.unpack('=3l16h', keydict['TZI'])
  82. self.stdoffset = -tup[0] - tup[1] # Bias + StandardBias * -1
  83. self.dstoffset = self.stdoffset - tup[2] # + DaylightBias * -1
  84. offset = 3
  85. self.stdmonth = tup[1 + offset]
  86. self.stddayofweek = tup[2 + offset] # Sunday=0
  87. self.stdweeknumber = tup[3 + offset] # Last = 5
  88. self.stdhour = tup[4 + offset]
  89. self.stdminute = tup[5 + offset]
  90. offset = 11
  91. self.dstmonth = tup[1 + offset]
  92. self.dstdayofweek = tup[2 + offset] # Sunday=0
  93. self.dstweeknumber = tup[3 + offset] # Last = 5
  94. self.dsthour = tup[4 + offset]
  95. self.dstminute = tup[5 + offset]
  96. else:
  97. keydict = valuesToDict(localkey)
  98. self.stdname = keydict['StandardName']
  99. self.dstname = keydict['DaylightName']
  100. sourcekey = _winreg.OpenKey(tzparent, self.stdname)
  101. self.display = valuesToDict(sourcekey)['Display']
  102. self.stdoffset = -keydict['Bias'] - keydict['StandardBias']
  103. self.dstoffset = self.stdoffset - keydict['DaylightBias']
  104. #see http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
  105. tup = struct.unpack('=8h', keydict['StandardStart'])
  106. offset = 0
  107. self.stdmonth = tup[1 + offset]
  108. self.stddayofweek = tup[2 + offset] # Sunday=0
  109. self.stdweeknumber = tup[3 + offset] # Last = 5
  110. self.stdhour = tup[4 + offset]
  111. self.stdminute = tup[5 + offset]
  112. tup = struct.unpack('=8h', keydict['DaylightStart'])
  113. self.dstmonth = tup[1 + offset]
  114. self.dstdayofweek = tup[2 + offset] # Sunday=0
  115. self.dstweeknumber = tup[3 + offset] # Last = 5
  116. self.dsthour = tup[4 + offset]
  117. self.dstminute = tup[5 + offset]
  118. def valuesToDict(key):
  119. """Convert a registry key's values to a dictionary."""
  120. d = {}
  121. size = _winreg.QueryInfoKey(key)[1]
  122. for i in xrange(size):
  123. d[_winreg.EnumValue(key, i)[0]] = _winreg.EnumValue(key, i)[1]
  124. return d
  125. def _test():
  126. import win32tz, doctest
  127. doctest.testmod(win32tz, verbose=0)
  128. if __name__ == '__main__':
  129. _test()