00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 """Tools for representing MongoDB internal Timestamps.
00016 """
00017
00018 import calendar
00019 import datetime
00020
00021 from bson.tz_util import utc
00022
00023
00024 class Timestamp(object):
00025 """MongoDB internal timestamps used in the opLog.
00026 """
00027
00028 def __init__(self, time, inc):
00029 """Create a new :class:`Timestamp`.
00030
00031 This class is only for use with the MongoDB opLog. If you need
00032 to store a regular timestamp, please use a
00033 :class:`~datetime.datetime`.
00034
00035 Raises :class:`TypeError` if `time` is not an instance of
00036 :class: `int` or :class:`~datetime.datetime`, or `inc` is not
00037 an instance of :class:`int`. Raises :class:`ValueError` if
00038 `time` or `inc` is not in [0, 2**32).
00039
00040 :Parameters:
00041 - `time`: time in seconds since epoch UTC, or a naive UTC
00042 :class:`~datetime.datetime`, or an aware
00043 :class:`~datetime.datetime`
00044 - `inc`: the incrementing counter
00045
00046 .. versionchanged:: 1.7
00047 `time` can now be a :class:`~datetime.datetime` instance.
00048 """
00049 if isinstance(time, datetime.datetime):
00050 if time.utcoffset() is not None:
00051 time = time - time.utcoffset()
00052 time = int(calendar.timegm(time.timetuple()))
00053 if not isinstance(time, (int, long)):
00054 raise TypeError("time must be an instance of int")
00055 if not isinstance(inc, (int, long)):
00056 raise TypeError("inc must be an instance of int")
00057 if not 0 <= time < 2 ** 32:
00058 raise ValueError("time must be contained in [0, 2**32)")
00059 if not 0 <= inc < 2 ** 32:
00060 raise ValueError("inc must be contained in [0, 2**32)")
00061
00062 self.__time = time
00063 self.__inc = inc
00064
00065 @property
00066 def time(self):
00067 """Get the time portion of this :class:`Timestamp`.
00068 """
00069 return self.__time
00070
00071 @property
00072 def inc(self):
00073 """Get the inc portion of this :class:`Timestamp`.
00074 """
00075 return self.__inc
00076
00077 def __eq__(self, other):
00078 if isinstance(other, Timestamp):
00079 return (self.__time == other.time and self.__inc == other.inc)
00080 else:
00081 return NotImplemented
00082
00083 def __ne__(self, other):
00084 return not self == other
00085
00086 def __repr__(self):
00087 return "Timestamp(%s, %s)" % (self.__time, self.__inc)
00088
00089 def as_datetime(self):
00090 """Return a :class:`~datetime.datetime` instance corresponding
00091 to the time portion of this :class:`Timestamp`.
00092
00093 .. versionchanged:: 1.8
00094 The returned datetime is now timezone aware.
00095 """
00096 return datetime.datetime.fromtimestamp(self.__time, utc)