_tzhelper.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # -*- test-case-name: twisted.python.test.test_tzhelper -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Time zone utilities.
  6. """
  7. from datetime import datetime, timedelta, tzinfo
  8. __all__ = [
  9. "FixedOffsetTimeZone",
  10. "UTC",
  11. ]
  12. class FixedOffsetTimeZone(tzinfo):
  13. """
  14. Represents a fixed timezone offset (without daylight saving time).
  15. @ivar name: A L{str} giving the name of this timezone; the name just
  16. includes how much time this offset represents.
  17. @ivar offset: A L{timedelta} giving the amount of time this timezone is
  18. offset.
  19. """
  20. def __init__(self, offset, name=None):
  21. """
  22. Construct a L{FixedOffsetTimeZone} with a fixed offset.
  23. @param offset: a delta representing the offset from UTC.
  24. @type offset: L{timedelta}
  25. @param name: A name to be given for this timezone.
  26. @type name: L{str} or L{None}
  27. """
  28. self.offset = offset
  29. self.name = name
  30. @classmethod
  31. def fromSignHoursMinutes(cls, sign, hours, minutes):
  32. """
  33. Construct a L{FixedOffsetTimeZone} from an offset described by sign
  34. ('+' or '-'), hours, and minutes.
  35. @note: For protocol compatibility with AMP, this method never uses 'Z'
  36. @param sign: A string describing the positive or negative-ness of the
  37. offset.
  38. @param hours: The number of hours in the offset.
  39. @type hours: L{int}
  40. @param minutes: The number of minutes in the offset
  41. @type minutes: L{int}
  42. @return: A time zone with the given offset, and a name describing the
  43. offset.
  44. @rtype: L{FixedOffsetTimeZone}
  45. """
  46. name = "%s%02i:%02i" % (sign, hours, minutes)
  47. if sign == "-":
  48. hours = -hours
  49. minutes = -minutes
  50. elif sign != "+":
  51. raise ValueError("Invalid sign for timezone %r" % (sign,))
  52. return cls(timedelta(hours=hours, minutes=minutes), name)
  53. @classmethod
  54. def fromLocalTimeStamp(cls, timeStamp):
  55. """
  56. Create a time zone with a fixed offset corresponding to a time stamp in
  57. the system's locally configured time zone.
  58. @param timeStamp: a time stamp
  59. @type timeStamp: L{int}
  60. @return: a time zone
  61. @rtype: L{FixedOffsetTimeZone}
  62. """
  63. offset = (
  64. datetime.fromtimestamp(timeStamp) -
  65. datetime.utcfromtimestamp(timeStamp)
  66. )
  67. return cls(offset)
  68. def utcoffset(self, dt):
  69. """
  70. Return this timezone's offset from UTC.
  71. """
  72. return self.offset
  73. def dst(self, dt):
  74. """
  75. Return a zero C{datetime.timedelta} for the daylight saving time
  76. offset, since there is never one.
  77. """
  78. return timedelta(0)
  79. def tzname(self, dt):
  80. """
  81. Return a string describing this timezone.
  82. """
  83. if self.name is not None:
  84. return self.name
  85. # XXX this is wrong; the tests are
  86. dt = datetime.fromtimestamp(0, self)
  87. return dt.strftime("UTC%z")
  88. UTC = FixedOffsetTimeZone.fromSignHoursMinutes("+", 0, 0)