annotate mercurial/dirstateutils/timestamp.py @ 50896:b2b8c25f9462

hgwebmod: use sysstr to check for attribute presence We do not need bytes here.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 30 Aug 2023 13:28:09 +0200
parents 6000f5b25c9b
children f4733654f144
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
1 # Copyright Mercurial Contributors
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
2 #
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
3 # This software may be used and distributed according to the terms of the
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
4 # GNU General Public License version 2 or any later version.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
5
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
6
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
7 import functools
48379
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
8 import os
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
9 import stat
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
10
48397
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
11 from .. import error
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
12
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
13
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
14 rangemask = 0x7FFFFFFF
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
15
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
16
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
17 @functools.total_ordering
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
18 class timestamp(tuple):
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
19 """
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
20 A Unix timestamp with optional nanoseconds precision,
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
21 modulo 2**31 seconds.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
22
48442
c8ca21962ff4 dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
23 A 3-tuple containing:
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
24
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
25 `truncated_seconds`: seconds since the Unix epoch,
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
26 truncated to its lower 31 bits
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
27
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
28 `subsecond_nanoseconds`: number of nanoseconds since `truncated_seconds`.
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
29 When this is zero, the sub-second precision is considered unknown.
48442
c8ca21962ff4 dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
30
c8ca21962ff4 dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
31 `second_ambiguous`: whether this timestamp is still "reliable"
c8ca21962ff4 dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
32 (see `reliable_mtime_of`) if we drop its sub-second component.
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
33 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
34
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
35 def __new__(cls, value):
48398
111098af6356 dirstate-item: add a "second_ambiguous` flag in the mtime tuple
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48397
diff changeset
36 truncated_seconds, subsec_nanos, second_ambiguous = value
111098af6356 dirstate-item: add a "second_ambiguous` flag in the mtime tuple
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48397
diff changeset
37 value = (truncated_seconds & rangemask, subsec_nanos, second_ambiguous)
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
38 return super(timestamp, cls).__new__(cls, value)
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
39
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
40 def __eq__(self, other):
48397
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
41 raise error.ProgrammingError(
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
42 'timestamp should never be compared directly'
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
43 )
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
44
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
45 def __gt__(self, other):
48397
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
46 raise error.ProgrammingError(
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
47 'timestamp should never be compared directly'
8d585aa9becf dirstate: drop comparison primitive on the timestamp class
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48395
diff changeset
48 )
48262
68bb472aee9c dirstate: ignore sub-second component when either is zero in mtime
Simon Sapin <simon.sapin@octobus.net>
parents: 48260
diff changeset
49
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
50
48379
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
51 def get_fs_now(vfs):
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
52 """return a timestamp for "now" in the current vfs
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
53
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
54 This will raise an exception if no temporary files could be created.
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
55 """
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
56 tmpfd, tmpname = vfs.mkstemp()
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
57 try:
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
58 return mtime_of(os.fstat(tmpfd))
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
59 finally:
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
60 os.close(tmpfd)
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
61 vfs.unlink(tmpname)
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
62
08b060abd658 dirstate: move "get fs now" in the timestamp utility module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48263
diff changeset
63
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
64 def zero():
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
65 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
66 Returns the `timestamp` at the Unix epoch.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
67 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
68 return tuple.__new__(timestamp, (0, 0))
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
69
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
70
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
71 def mtime_of(stat_result):
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
72 """
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
73 Takes an `os.stat_result`-like object and returns a `timestamp` object
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
74 for its modification time.
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
75 """
48263
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
76 try:
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
77 # TODO: add this attribute to `osutil.stat` objects,
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
78 # see `mercurial/cext/osutil.c`.
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
79 #
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
80 # This attribute is also not available on Python 2.
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
81 nanos = stat_result.st_mtime_ns
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
82 except AttributeError:
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
83 # https://docs.python.org/2/library/os.html#os.stat_float_times
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
84 # "For compatibility with older Python versions,
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
85 # accessing stat_result as a tuple always returns integers."
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
86 secs = stat_result[stat.ST_MTIME]
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
87
48263
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
88 subsec_nanos = 0
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
89 else:
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
90 billion = int(1e9)
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
91 secs = nanos // billion
83d0bd45b662 dirstate-v2: actually use sub-second mtime precision
Simon Sapin <simon.sapin@octobus.net>
parents: 48262
diff changeset
92 subsec_nanos = nanos % billion
48260
269ff8978086 dirstate: store mtimes with nanosecond precision in memory
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
93
48398
111098af6356 dirstate-item: add a "second_ambiguous` flag in the mtime tuple
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48397
diff changeset
94 return timestamp((secs, subsec_nanos, False))
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
95
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
96
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
97 def reliable_mtime_of(stat_result, present_mtime):
48442
c8ca21962ff4 dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
98 """Same as `mtime_of`, but return `None` or a `Timestamp` with
c8ca21962ff4 dirstate: Document Timestamp.second_ambiguous
Simon Sapin <simon.sapin@octobus.net>
parents: 48422
diff changeset
99 `second_ambiguous` set if the date might be ambiguous.
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
100
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
101 A modification time is reliable if it is older than "present_time" (or
48422
000130cfafb6 rhg: Update the dirstate on disk after status
Simon Sapin <simon.sapin@octobus.net>
parents: 48403
diff changeset
102 sufficiently in the future).
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
103
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
104 Otherwise a concurrent modification might happens with the same mtime.
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
105 """
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
106 file_mtime = mtime_of(stat_result)
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
107 file_second = file_mtime[0]
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
108 file_ns = file_mtime[1]
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
109 boundary_second = present_mtime[0]
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
110 boundary_ns = present_mtime[1]
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
111 # If the mtime of the ambiguous file is younger (or equal) to the starting
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
112 # point of the `status` walk, we cannot garantee that another, racy, write
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
113 # will not happen right after with the same mtime and we cannot cache the
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
114 # information.
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
115 #
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
116 # However if the mtime is far away in the future, this is likely some
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
117 # mismatch between the current clock and previous file system operation. So
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
118 # mtime more than one days in the future are considered fine.
48403
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
119 if boundary_second == file_second:
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
120 if file_ns and boundary_ns:
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
121 if file_ns < boundary_ns:
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
122 return timestamp((file_second, file_ns, True))
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
123 return None
ca42667c8d26 status: keep second-ambiguous mtimes during fixup
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48398
diff changeset
124 elif boundary_second < file_second < (3600 * 24 + boundary_second):
48395
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
125 return None
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
126 else:
9ae0353c9f5d status: move the boundary comparison logic within the timestamp module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 48379
diff changeset
127 return file_mtime