77
88PY2 = sys .version_info [0 ] == 2
99
10- if not PY2 :
11- long = int
10+ if PY2 :
11+ int_types = (int , long )
12+ _utc = None
13+ else :
14+ int_types = int
1215 try :
1316 _utc = datetime .timezone .utc
1417 except AttributeError :
@@ -23,8 +26,6 @@ def __new__(cls, code, data):
2326 raise TypeError ("code must be int" )
2427 if not isinstance (data , bytes ):
2528 raise TypeError ("data must be bytes" )
26- if code == - 1 :
27- return Timestamp .from_bytes (data )
2829 if not 0 <= code <= 127 :
2930 raise ValueError ("code must be 0~127" )
3031 return super (ExtType , cls ).__new__ (cls , code , data )
@@ -42,34 +43,26 @@ class Timestamp(object):
4243 def __init__ (self , seconds , nanoseconds = 0 ):
4344 """Initialize a Timestamp object.
4445
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.
4849
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.
5253
5354 Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns.
5455 """
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 ):
5859 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
7366
7467 def __repr__ (self ):
7568 """String representation of Timestamp."""
@@ -137,7 +130,18 @@ def to_bytes(self):
137130 data = struct .pack ("!Iq" , self .nanoseconds , self .seconds )
138131 return data
139132
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 ):
141145 """Get the timestamp as a floating-point value.
142146
143147 :returns: posix timestamp
@@ -146,28 +150,37 @@ def to_float(self):
146150 return self .seconds + self .nanoseconds / 1e9
147151
148152 @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.
153155
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 ):
155162 """Get the timestamp as a unixtime in nanoseconds.
156163
157164 :returns: posix timestamp in nanoseconds
158165 :rtype: int
159166 """
160- return int ( self .seconds * 1e9 + self .nanoseconds )
167+ return self .seconds * 10 ** 9 + self .nanoseconds
161168
162- if not PY2 :
169+ def to_datetime (self ):
170+ """Get the timestamp as a UTC datetime.
163171
164- def to_datetime (self ):
165- """Get the timestamp as a UTC datetime.
172+ Python 2 is not supported.
166173
167- :rtype: datetime.
168- """
169- return datetime .datetime .fromtimestamp (self .to_float (), _utc )
174+ :rtype: datetime.
175+ """
176+ return datetime .datetime .fromtimestamp (self .to_unix (), _utc )
170177
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