timestamp.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. # Copyright 2010-2015 MongoDB, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Tools for representing MongoDB internal Timestamps.
  15. """
  16. import calendar
  17. import datetime
  18. from bson.py3compat import integer_types
  19. from bson.tz_util import utc
  20. UPPERBOUND = 4294967296
  21. class Timestamp(object):
  22. """MongoDB internal timestamps used in the opLog.
  23. """
  24. _type_marker = 17
  25. def __init__(self, time, inc):
  26. """Create a new :class:`Timestamp`.
  27. This class is only for use with the MongoDB opLog. If you need
  28. to store a regular timestamp, please use a
  29. :class:`~datetime.datetime`.
  30. Raises :class:`TypeError` if `time` is not an instance of
  31. :class: `int` or :class:`~datetime.datetime`, or `inc` is not
  32. an instance of :class:`int`. Raises :class:`ValueError` if
  33. `time` or `inc` is not in [0, 2**32).
  34. :Parameters:
  35. - `time`: time in seconds since epoch UTC, or a naive UTC
  36. :class:`~datetime.datetime`, or an aware
  37. :class:`~datetime.datetime`
  38. - `inc`: the incrementing counter
  39. """
  40. if isinstance(time, datetime.datetime):
  41. if time.utcoffset() is not None:
  42. time = time - time.utcoffset()
  43. time = int(calendar.timegm(time.timetuple()))
  44. if not isinstance(time, integer_types):
  45. raise TypeError("time must be an instance of int")
  46. if not isinstance(inc, integer_types):
  47. raise TypeError("inc must be an instance of int")
  48. if not 0 <= time < UPPERBOUND:
  49. raise ValueError("time must be contained in [0, 2**32)")
  50. if not 0 <= inc < UPPERBOUND:
  51. raise ValueError("inc must be contained in [0, 2**32)")
  52. self.__time = time
  53. self.__inc = inc
  54. @property
  55. def time(self):
  56. """Get the time portion of this :class:`Timestamp`.
  57. """
  58. return self.__time
  59. @property
  60. def inc(self):
  61. """Get the inc portion of this :class:`Timestamp`.
  62. """
  63. return self.__inc
  64. def __eq__(self, other):
  65. if isinstance(other, Timestamp):
  66. return (self.__time == other.time and self.__inc == other.inc)
  67. else:
  68. return NotImplemented
  69. def __hash__(self):
  70. return hash(self.time) ^ hash(self.inc)
  71. def __ne__(self, other):
  72. return not self == other
  73. def __lt__(self, other):
  74. if isinstance(other, Timestamp):
  75. return (self.time, self.inc) < (other.time, other.inc)
  76. return NotImplemented
  77. def __le__(self, other):
  78. if isinstance(other, Timestamp):
  79. return (self.time, self.inc) <= (other.time, other.inc)
  80. return NotImplemented
  81. def __gt__(self, other):
  82. if isinstance(other, Timestamp):
  83. return (self.time, self.inc) > (other.time, other.inc)
  84. return NotImplemented
  85. def __ge__(self, other):
  86. if isinstance(other, Timestamp):
  87. return (self.time, self.inc) >= (other.time, other.inc)
  88. return NotImplemented
  89. def __repr__(self):
  90. return "Timestamp(%s, %s)" % (self.__time, self.__inc)
  91. def as_datetime(self):
  92. """Return a :class:`~datetime.datetime` instance corresponding
  93. to the time portion of this :class:`Timestamp`.
  94. The returned datetime's timezone is UTC.
  95. """
  96. return datetime.datetime.fromtimestamp(self.__time, utc)