# Copyright Mercurial Contributors # # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. from __future__ import absolute_import import functools import stat rangemask = 0x7FFFFFFF @functools.total_ordering class timestamp(tuple): """ A Unix timestamp with optional nanoseconds precision, modulo 2**31 seconds. A 2-tuple containing: `truncated_seconds`: seconds since the Unix epoch, truncated to its lower 31 bits `subsecond_nanoseconds`: number of nanoseconds since `truncated_seconds`. When this is zero, the sub-second precision is considered unknown. """ def __new__(cls, value): truncated_seconds, subsec_nanos = value value = (truncated_seconds & rangemask, subsec_nanos) return super(timestamp, cls).__new__(cls, value) def __eq__(self, other): self_secs, self_subsec_nanos = self other_secs, other_subsec_nanos = other return self_secs == other_secs and ( self_subsec_nanos == other_subsec_nanos or self_subsec_nanos == 0 or other_subsec_nanos == 0 ) def __gt__(self, other): self_secs, self_subsec_nanos = self other_secs, other_subsec_nanos = other if self_secs > other_secs: return True if self_secs < other_secs: return False if self_subsec_nanos == 0 or other_subsec_nanos == 0: # they are considered equal, so not "greater than" return False return self_subsec_nanos > other_subsec_nanos def zero(): """ Returns the `timestamp` at the Unix epoch. """ return tuple.__new__(timestamp, (0, 0)) def mtime_of(stat_result): """ Takes an `os.stat_result`-like object and returns a `timestamp` object for its modification time. """ try: # TODO: add this attribute to `osutil.stat` objects, # see `mercurial/cext/osutil.c`. # # This attribute is also not available on Python 2. nanos = stat_result.st_mtime_ns except AttributeError: # https://docs.python.org/2/library/os.html#os.stat_float_times # "For compatibility with older Python versions, # accessing stat_result as a tuple always returns integers." secs = stat_result[stat.ST_MTIME] subsec_nanos = 0 else: billion = int(1e9) secs = nanos // billion subsec_nanos = nanos % billion return timestamp((secs, subsec_nanos))