7
7
8
8
PY2 = sys .version_info [0 ] == 2
9
9
10
- if not PY2 :
11
- long = int
10
+ if PY2 :
11
+ int_types = (int , long )
12
+ _utc = None
13
+ else :
14
+ int_types = int
12
15
try :
13
16
_utc = datetime .timezone .utc
14
17
except AttributeError :
@@ -23,8 +26,6 @@ def __new__(cls, code, data):
23
26
raise TypeError ("code must be int" )
24
27
if not isinstance (data , bytes ):
25
28
raise TypeError ("data must be bytes" )
26
- if code == - 1 :
27
- return Timestamp .from_bytes (data )
28
29
if not 0 <= code <= 127 :
29
30
raise ValueError ("code must be 0~127" )
30
31
return super (ExtType , cls ).__new__ (cls , code , data )
@@ -42,34 +43,26 @@ class Timestamp(object):
42
43
def __init__ (self , seconds , nanoseconds = 0 ):
43
44
"""Initialize a Timestamp object.
44
45
45
- :param seconds: Number of seconds since the UNIX epoch (00:00:00 UTC Jan 1 1970, minus leap seconds). May be
46
- negative. If :code:` seconds` includes a fractional part, :code:`nanoseconds` must be 0 .
47
- :type seconds: int or float
46
+ :param int seconds:
47
+ Number of seconds since the UNIX epoch (00:00:00 UTC Jan 1 1970, minus leap seconds) .
48
+ May be negative.
48
49
49
- :param nanoseconds: Number of nanoseconds to add to `seconds` to get fractional time. Maximum is 999_999_999.
50
- Default is 0 .
51
- :type nanoseconds: int
50
+ :param int nanoseconds:
51
+ Number of nanoseconds to add to `seconds` to get fractional time .
52
+ Maximum is 999_999_999. Default is 0.
52
53
53
54
Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns.
54
55
"""
55
- if not isinstance (seconds , ( int , long , float ) ):
56
- raise TypeError ("seconds must be numeric " )
57
- if not isinstance (nanoseconds , ( int , long ) ):
56
+ if not isinstance (seconds , int_types ):
57
+ raise TypeError ("seconds must be an interger " )
58
+ if not isinstance (nanoseconds , int_types ):
58
59
raise TypeError ("nanoseconds must be an integer" )
59
- if nanoseconds :
60
- if nanoseconds < 0 or nanoseconds % 1 != 0 or nanoseconds > (1e9 - 1 ):
61
- raise ValueError (
62
- "nanoseconds must be a non-negative integer less than 999999999."
63
- )
64
- if not isinstance (seconds , (int , long )):
65
- raise ValueError (
66
- "seconds must be an integer if also providing nanoseconds."
67
- )
68
- self .nanoseconds = nanoseconds
69
- else :
70
- # round helps with floating point issues
71
- self .nanoseconds = int (round (seconds % 1 * 1e9 , 0 ))
72
- self .seconds = int (seconds // 1 )
60
+ if not (0 <= nanoseconds < 10 ** 9 ):
61
+ raise ValueError (
62
+ "nanoseconds must be a non-negative integer less than 999999999."
63
+ )
64
+ self .seconds = seconds
65
+ self .nanoseconds = nanoseconds
73
66
74
67
def __repr__ (self ):
75
68
"""String representation of Timestamp."""
@@ -137,7 +130,18 @@ def to_bytes(self):
137
130
data = struct .pack ("!Iq" , self .nanoseconds , self .seconds )
138
131
return data
139
132
140
- def to_float (self ):
133
+ @staticmethod
134
+ def from_unix (unix_sec ):
135
+ """Create a Timestamp from posix timestamp in seconds.
136
+
137
+ :param unix_float: Posix timestamp in seconds.
138
+ :type unix_float: int or float.
139
+ """
140
+ seconds = int (unix_sec // 1 )
141
+ nanoseconds = int ((unix_sec % 1 ) * 10 ** 9 )
142
+ return Timestamp (seconds , nanoseconds )
143
+
144
+ def to_unix (self ):
141
145
"""Get the timestamp as a floating-point value.
142
146
143
147
:returns: posix timestamp
@@ -146,28 +150,37 @@ def to_float(self):
146
150
return self .seconds + self .nanoseconds / 1e9
147
151
148
152
@staticmethod
149
- def from_float (unix_float ):
150
- seconds = int (unix_float )
151
- nanoseconds = int ((unix_float % 1 ) * 1000000000 )
152
- return Timestamp (seconds , nanoseconds )
153
+ def from_unix_nano (unix_ns ):
154
+ """Create a Timestamp from posix timestamp in nanoseconds.
153
155
154
- def to_unix_ns (self ):
156
+ :param int unix_ns: Posix timestamp in nanoseconds.
157
+ :rtype: Timestamp
158
+ """
159
+ return Timestamp (* divmod (unix_ns , 10 ** 9 ))
160
+
161
+ def to_unix_nano (self ):
155
162
"""Get the timestamp as a unixtime in nanoseconds.
156
163
157
164
:returns: posix timestamp in nanoseconds
158
165
:rtype: int
159
166
"""
160
- return int ( self .seconds * 1e9 + self .nanoseconds )
167
+ return self .seconds * 10 ** 9 + self .nanoseconds
161
168
162
- if not PY2 :
169
+ def to_datetime (self ):
170
+ """Get the timestamp as a UTC datetime.
163
171
164
- def to_datetime (self ):
165
- """Get the timestamp as a UTC datetime.
172
+ Python 2 is not supported.
166
173
167
- :rtype: datetime.
168
- """
169
- return datetime .datetime .fromtimestamp (self .to_float (), _utc )
174
+ :rtype: datetime.
175
+ """
427E
176
+ return datetime .datetime .fromtimestamp (self .to_unix (), _utc )
170
177
171
- @staticmethod
172
- def from_datetime (dt ):
173
- return Timestamp .from_float (dt .timestamp ())
178
+ @staticmethod
179
+ def from_datetime (dt ):
180
+ """Create a Timestamp from datetime with tzinfo.
181
+
182
+ Python 2 is not supported.
183
+
184
+ :rtype: Timestamp
185
+ """
186
+ return Timestamp .from_unix (dt .timestamp ())
0 commit comments