11from __future__ import annotations
22
33import re
4+ from datetime import UTC , datetime
45
5- import pendulum
6- from pendulum .datetime import DateTime
6+ from whenever import Date , Instant , Time , ZonedDateTime
77
88REGEX_MAPPING = {
99 "seconds" : r"(\d+)(s|sec|second|seconds)" ,
@@ -16,47 +16,67 @@ class TimestampFormatError(ValueError): ...
1616
1717
1818class Timestamp :
19- def __init__ (self , value : str | DateTime | Timestamp | None = None ):
20- if value and isinstance (value , DateTime ):
19+ obj : ZonedDateTime
20+
21+ def __init__ (self , value : str | ZonedDateTime | Timestamp | None = None ):
22+ if value and isinstance (value , ZonedDateTime ):
2123 self .obj = value
2224 elif value and isinstance (value , self .__class__ ):
2325 self .obj = value .obj
2426 elif isinstance (value , str ):
2527 self .obj = self ._parse_string (value )
2628 else :
27- self .obj = DateTime .now (tz = "UTC" )
29+ self .obj = ZonedDateTime .now ("UTC" )
2830
2931 @classmethod
30- def _parse_string (cls , value : str ) -> DateTime :
32+ def _parse_string (cls , value : str ) -> ZonedDateTime :
33+ try :
34+ zoned_date = ZonedDateTime .parse_common_iso (value )
35+ return zoned_date
36+ except ValueError :
37+ pass
38+
3139 try :
32- parsed_date = pendulum .parse (value )
33- if isinstance (parsed_date , DateTime ):
34- return parsed_date
35- except (pendulum .parsing .exceptions .ParserError , ValueError ):
40+ instant_date_ = Instant .parse_common_iso (value )
41+ return instant_date_ .to_tz ("UTC" )
42+ except ValueError :
3643 pass
3744
38- params = {}
45+ try :
46+ date = Date .parse_common_iso (value )
47+ local_date = date .at (Time (12 , 00 ))
48+ return local_date .assume_tz ("UTC" )
49+ except ValueError :
50+ pass
51+
52+ params : dict [str , float ] = {}
3953 for key , regex in REGEX_MAPPING .items ():
4054 match = re .search (regex , value )
4155 if match :
42- params [key ] = int (match .group (1 ))
56+ params [key ] = float (match .group (1 ))
4357
44- if not params :
45- raise TimestampFormatError ( f"Invalid time format for { value } " )
58+ if params :
59+ return ZonedDateTime . now ( "UTC" ). subtract ( ** params ) # type: ignore[call-overload]
4660
47- return DateTime . now ( tz = "UTC" ). subtract ( ** params )
61+ raise TimestampFormatError ( f"Invalid time format for { value } " )
4862
4963 def __repr__ (self ) -> str :
5064 return f"Timestamp: { self .to_string ()} "
5165
5266 def to_string (self , with_z : bool = True ) -> str :
53- iso8601_string = self .obj .to_iso8601_string ()
54- if not with_z and iso8601_string [- 1 ] == "Z" :
67+ if with_z :
68+ return self .obj .instant ().format_common_iso ()
69+ iso8601_string = self .obj .format_common_iso ()
70+ if iso8601_string [- 1 ] == "Z" :
5571 iso8601_string = iso8601_string [:- 1 ] + "+00:00"
5672 return iso8601_string
5773
5874 def to_timestamp (self ) -> int :
59- return self .obj .int_timestamp
75+ return self .obj .timestamp ()
76+
77+ def to_datetime (self ) -> datetime :
78+ time_str = self .to_string ()
79+ return datetime .strptime (time_str [:- 1 ], "%Y-%m-%dT%H:%M:%S.%f" ).replace (tzinfo = UTC )
6080
6181 def __eq__ (self , other : object ) -> bool :
6282 if not isinstance (other , Timestamp ):
0 commit comments