Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/arrow/factory.py: 29%
89 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:26 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-12-08 06:26 +0000
1"""
2Implements the :class:`ArrowFactory <arrow.factory.ArrowFactory>` class,
3providing factory methods for common :class:`Arrow <arrow.arrow.Arrow>`
4construction scenarios.
6"""
9import calendar
10from datetime import date, datetime
11from datetime import tzinfo as dt_tzinfo
12from decimal import Decimal
13from time import struct_time
14from typing import Any, List, Optional, Tuple, Type, Union, overload
16from dateutil import tz as dateutil_tz
18from arrow import parser
19from arrow.arrow import TZ_EXPR, Arrow
20from arrow.constants import DEFAULT_LOCALE
21from arrow.util import is_timestamp, iso_to_gregorian
24class ArrowFactory:
25 """A factory for generating :class:`Arrow <arrow.arrow.Arrow>` objects.
27 :param type: (optional) the :class:`Arrow <arrow.arrow.Arrow>`-based class to construct from.
28 Defaults to :class:`Arrow <arrow.arrow.Arrow>`.
30 """
32 type: Type[Arrow]
34 def __init__(self, type: Type[Arrow] = Arrow) -> None:
35 self.type = type
37 @overload
38 def get(
39 self,
40 *,
41 locale: str = DEFAULT_LOCALE,
42 tzinfo: Optional[TZ_EXPR] = None,
43 normalize_whitespace: bool = False,
44 ) -> Arrow:
45 ... # pragma: no cover
47 @overload
48 def get(
49 self,
50 __obj: Union[
51 Arrow,
52 datetime,
53 date,
54 struct_time,
55 dt_tzinfo,
56 int,
57 float,
58 str,
59 Tuple[int, int, int],
60 ],
61 *,
62 locale: str = DEFAULT_LOCALE,
63 tzinfo: Optional[TZ_EXPR] = None,
64 normalize_whitespace: bool = False,
65 ) -> Arrow:
66 ... # pragma: no cover
68 @overload
69 def get(
70 self,
71 __arg1: Union[datetime, date],
72 __arg2: TZ_EXPR,
73 *,
74 locale: str = DEFAULT_LOCALE,
75 tzinfo: Optional[TZ_EXPR] = None,
76 normalize_whitespace: bool = False,
77 ) -> Arrow:
78 ... # pragma: no cover
80 @overload
81 def get(
82 self,
83 __arg1: str,
84 __arg2: Union[str, List[str]],
85 *,
86 locale: str = DEFAULT_LOCALE,
87 tzinfo: Optional[TZ_EXPR] = None,
88 normalize_whitespace: bool = False,
89 ) -> Arrow:
90 ... # pragma: no cover
92 def get(self, *args: Any, **kwargs: Any) -> Arrow:
93 """Returns an :class:`Arrow <arrow.arrow.Arrow>` object based on flexible inputs.
95 :param locale: (optional) a ``str`` specifying a locale for the parser. Defaults to 'en-us'.
96 :param tzinfo: (optional) a :ref:`timezone expression <tz-expr>` or tzinfo object.
97 Replaces the timezone unless using an input form that is explicitly UTC or specifies
98 the timezone in a positional argument. Defaults to UTC.
99 :param normalize_whitespace: (optional) a ``bool`` specifying whether or not to normalize
100 redundant whitespace (spaces, tabs, and newlines) in a datetime string before parsing.
101 Defaults to false.
103 Usage::
105 >>> import arrow
107 **No inputs** to get current UTC time::
109 >>> arrow.get()
110 <Arrow [2013-05-08T05:51:43.316458+00:00]>
112 **One** :class:`Arrow <arrow.arrow.Arrow>` object, to get a copy.
114 >>> arw = arrow.utcnow()
115 >>> arrow.get(arw)
116 <Arrow [2013-10-23T15:21:54.354846+00:00]>
118 **One** ``float`` or ``int``, convertible to a floating-point timestamp, to get
119 that timestamp in UTC::
121 >>> arrow.get(1367992474.293378)
122 <Arrow [2013-05-08T05:54:34.293378+00:00]>
124 >>> arrow.get(1367992474)
125 <Arrow [2013-05-08T05:54:34+00:00]>
127 **One** ISO 8601-formatted ``str``, to parse it::
129 >>> arrow.get('2013-09-29T01:26:43.830580')
130 <Arrow [2013-09-29T01:26:43.830580+00:00]>
132 **One** ISO 8601-formatted ``str``, in basic format, to parse it::
134 >>> arrow.get('20160413T133656.456289')
135 <Arrow [2016-04-13T13:36:56.456289+00:00]>
137 **One** ``tzinfo``, to get the current time **converted** to that timezone::
139 >>> arrow.get(tz.tzlocal())
140 <Arrow [2013-05-07T22:57:28.484717-07:00]>
142 **One** naive ``datetime``, to get that datetime in UTC::
144 >>> arrow.get(datetime(2013, 5, 5))
145 <Arrow [2013-05-05T00:00:00+00:00]>
147 **One** aware ``datetime``, to get that datetime::
149 >>> arrow.get(datetime(2013, 5, 5, tzinfo=tz.tzlocal()))
150 <Arrow [2013-05-05T00:00:00-07:00]>
152 **One** naive ``date``, to get that date in UTC::
154 >>> arrow.get(date(2013, 5, 5))
155 <Arrow [2013-05-05T00:00:00+00:00]>
157 **One** time.struct time::
159 >>> arrow.get(gmtime(0))
160 <Arrow [1970-01-01T00:00:00+00:00]>
162 **One** iso calendar ``tuple``, to get that week date in UTC::
164 >>> arrow.get((2013, 18, 7))
165 <Arrow [2013-05-05T00:00:00+00:00]>
167 **Two** arguments, a naive or aware ``datetime``, and a replacement
168 :ref:`timezone expression <tz-expr>`::
170 >>> arrow.get(datetime(2013, 5, 5), 'US/Pacific')
171 <Arrow [2013-05-05T00:00:00-07:00]>
173 **Two** arguments, a naive ``date``, and a replacement
174 :ref:`timezone expression <tz-expr>`::
176 >>> arrow.get(date(2013, 5, 5), 'US/Pacific')
177 <Arrow [2013-05-05T00:00:00-07:00]>
179 **Two** arguments, both ``str``, to parse the first according to the format of the second::
181 >>> arrow.get('2013-05-05 12:30:45 America/Chicago', 'YYYY-MM-DD HH:mm:ss ZZZ')
182 <Arrow [2013-05-05T12:30:45-05:00]>
184 **Two** arguments, first a ``str`` to parse and second a ``list`` of formats to try::
186 >>> arrow.get('2013-05-05 12:30:45', ['MM/DD/YYYY', 'YYYY-MM-DD HH:mm:ss'])
187 <Arrow [2013-05-05T12:30:45+00:00]>
189 **Three or more** arguments, as for the direct constructor of an ``Arrow`` object::
191 >>> arrow.get(2013, 5, 5, 12, 30, 45)
192 <Arrow [2013-05-05T12:30:45+00:00]>
194 """
196 arg_count = len(args)
197 locale = kwargs.pop("locale", DEFAULT_LOCALE)
198 tz = kwargs.get("tzinfo", None)
199 normalize_whitespace = kwargs.pop("normalize_whitespace", False)
201 # if kwargs given, send to constructor unless only tzinfo provided
202 if len(kwargs) > 1:
203 arg_count = 3
205 # tzinfo kwarg is not provided
206 if len(kwargs) == 1 and tz is None:
207 arg_count = 3
209 # () -> now, @ tzinfo or utc
210 if arg_count == 0:
211 if isinstance(tz, str):
212 tz = parser.TzinfoParser.parse(tz)
213 return self.type.now(tzinfo=tz)
215 if isinstance(tz, dt_tzinfo):
216 return self.type.now(tzinfo=tz)
218 return self.type.utcnow()
220 if arg_count == 1:
221 arg = args[0]
222 if isinstance(arg, Decimal):
223 arg = float(arg)
225 # (None) -> raises an exception
226 if arg is None:
227 raise TypeError("Cannot parse argument of type None.")
229 # try (int, float) -> from timestamp @ tzinfo
230 elif not isinstance(arg, str) and is_timestamp(arg):
231 if tz is None:
232 # set to UTC by default
233 tz = dateutil_tz.tzutc()
234 return self.type.fromtimestamp(arg, tzinfo=tz)
236 # (Arrow) -> from the object's datetime @ tzinfo
237 elif isinstance(arg, Arrow):
238 return self.type.fromdatetime(arg.datetime, tzinfo=tz)
240 # (datetime) -> from datetime @ tzinfo
241 elif isinstance(arg, datetime):
242 return self.type.fromdatetime(arg, tzinfo=tz)
244 # (date) -> from date @ tzinfo
245 elif isinstance(arg, date):
246 return self.type.fromdate(arg, tzinfo=tz)
248 # (tzinfo) -> now @ tzinfo
249 elif isinstance(arg, dt_tzinfo):
250 return self.type.now(tzinfo=arg)
252 # (str) -> parse @ tzinfo
253 elif isinstance(arg, str):
254 dt = parser.DateTimeParser(locale).parse_iso(arg, normalize_whitespace)
255 return self.type.fromdatetime(dt, tzinfo=tz)
257 # (struct_time) -> from struct_time
258 elif isinstance(arg, struct_time):
259 return self.type.utcfromtimestamp(calendar.timegm(arg))
261 # (iso calendar) -> convert then from date @ tzinfo
262 elif isinstance(arg, tuple) and len(arg) == 3:
263 d = iso_to_gregorian(*arg)
264 return self.type.fromdate(d, tzinfo=tz)
266 else:
267 raise TypeError(f"Cannot parse single argument of type {type(arg)!r}.")
269 elif arg_count == 2:
270 arg_1, arg_2 = args[0], args[1]
272 if isinstance(arg_1, datetime):
273 # (datetime, tzinfo/str) -> fromdatetime @ tzinfo
274 if isinstance(arg_2, (dt_tzinfo, str)):
275 return self.type.fromdatetime(arg_1, tzinfo=arg_2)
276 else:
277 raise TypeError(
278 f"Cannot parse two arguments of types 'datetime', {type(arg_2)!r}."
279 )
281 elif isinstance(arg_1, date):
282 # (date, tzinfo/str) -> fromdate @ tzinfo
283 if isinstance(arg_2, (dt_tzinfo, str)):
284 return self.type.fromdate(arg_1, tzinfo=arg_2)
285 else:
286 raise TypeError(
287 f"Cannot parse two arguments of types 'date', {type(arg_2)!r}."
288 )
290 # (str, format) -> parse @ tzinfo
291 elif isinstance(arg_1, str) and isinstance(arg_2, (str, list)):
292 dt = parser.DateTimeParser(locale).parse(
293 args[0], args[1], normalize_whitespace
294 )
295 return self.type.fromdatetime(dt, tzinfo=tz)
297 else:
298 raise TypeError(
299 f"Cannot parse two arguments of types {type(arg_1)!r} and {type(arg_2)!r}."
300 )
302 # 3+ args -> datetime-like via constructor
303 else:
304 return self.type(*args, **kwargs)
306 def utcnow(self) -> Arrow:
307 """Returns an :class:`Arrow <arrow.arrow.Arrow>` object, representing "now" in UTC time.
309 Usage::
311 >>> import arrow
312 >>> arrow.utcnow()
313 <Arrow [2013-05-08T05:19:07.018993+00:00]>
314 """
316 return self.type.utcnow()
318 def now(self, tz: Optional[TZ_EXPR] = None) -> Arrow:
319 """Returns an :class:`Arrow <arrow.arrow.Arrow>` object, representing "now" in the given
320 timezone.
322 :param tz: (optional) A :ref:`timezone expression <tz-expr>`. Defaults to local time.
324 Usage::
326 >>> import arrow
327 >>> arrow.now()
328 <Arrow [2013-05-07T22:19:11.363410-07:00]>
330 >>> arrow.now('US/Pacific')
331 <Arrow [2013-05-07T22:19:15.251821-07:00]>
333 >>> arrow.now('+02:00')
334 <Arrow [2013-05-08T07:19:25.618646+02:00]>
336 >>> arrow.now('local')
337 <Arrow [2013-05-07T22:19:39.130059-07:00]>
338 """
340 if tz is None:
341 tz = dateutil_tz.tzlocal()
342 elif not isinstance(tz, dt_tzinfo):
343 tz = parser.TzinfoParser.parse(tz)
345 return self.type.now(tz)