Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/arrow/factory.py: 26%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

85 statements  

1""" 

2Implements the :class:`ArrowFactory <arrow.factory.ArrowFactory>` class, 

3providing factory methods for common :class:`Arrow <arrow.arrow.Arrow>` 

4construction scenarios. 

5 

6""" 

7 

8import calendar 

9from datetime import date, datetime, timezone 

10from datetime import tzinfo as dt_tzinfo 

11from decimal import Decimal 

12from time import struct_time 

13from typing import Any, List, Optional, Tuple, Type, Union, overload 

14 

15from arrow import parser 

16from arrow.arrow import TZ_EXPR, Arrow 

17from arrow.constants import DEFAULT_LOCALE 

18from arrow.util import is_timestamp, iso_to_gregorian 

19 

20 

21class ArrowFactory: 

22 """A factory for generating :class:`Arrow <arrow.arrow.Arrow>` objects. 

23 

24 :param type: (optional) the :class:`Arrow <arrow.arrow.Arrow>`-based class to construct from. 

25 Defaults to :class:`Arrow <arrow.arrow.Arrow>`. 

26 

27 """ 

28 

29 type: Type[Arrow] 

30 

31 def __init__(self, type: Type[Arrow] = Arrow) -> None: 

32 self.type = type 

33 

34 @overload 

35 def get( 

36 self, 

37 *, 

38 locale: str = DEFAULT_LOCALE, 

39 tzinfo: Optional[TZ_EXPR] = None, 

40 normalize_whitespace: bool = False, 

41 ) -> Arrow: ... # pragma: no cover 

42 

43 @overload 

44 def get( 

45 self, 

46 __obj: Union[ 

47 Arrow, 

48 datetime, 

49 date, 

50 struct_time, 

51 dt_tzinfo, 

52 int, 

53 float, 

54 str, 

55 Tuple[int, int, int], 

56 ], 

57 *, 

58 locale: str = DEFAULT_LOCALE, 

59 tzinfo: Optional[TZ_EXPR] = None, 

60 normalize_whitespace: bool = False, 

61 ) -> Arrow: ... # pragma: no cover 

62 

63 @overload 

64 def get( 

65 self, 

66 __arg1: Union[datetime, date], 

67 __arg2: TZ_EXPR, 

68 *, 

69 locale: str = DEFAULT_LOCALE, 

70 tzinfo: Optional[TZ_EXPR] = None, 

71 normalize_whitespace: bool = False, 

72 ) -> Arrow: ... # pragma: no cover 

73 

74 @overload 

75 def get( 

76 self, 

77 __arg1: str, 

78 __arg2: Union[str, List[str]], 

79 *, 

80 locale: str = DEFAULT_LOCALE, 

81 tzinfo: Optional[TZ_EXPR] = None, 

82 normalize_whitespace: bool = False, 

83 ) -> Arrow: ... # pragma: no cover 

84 

85 def get(self, *args: Any, **kwargs: Any) -> Arrow: 

86 """Returns an :class:`Arrow <arrow.arrow.Arrow>` object based on flexible inputs. 

87 

88 :param locale: (optional) a ``str`` specifying a locale for the parser. Defaults to 'en-us'. 

89 :param tzinfo: (optional) a :ref:`timezone expression <tz-expr>` or tzinfo object. 

90 Replaces the timezone unless using an input form that is explicitly UTC or specifies 

91 the timezone in a positional argument. Defaults to UTC. 

92 :param normalize_whitespace: (optional) a ``bool`` specifying whether or not to normalize 

93 redundant whitespace (spaces, tabs, and newlines) in a datetime string before parsing. 

94 Defaults to false. 

95 

96 Usage:: 

97 

98 >>> import arrow 

99 

100 **No inputs** to get current UTC time:: 

101 

102 >>> arrow.get() 

103 <Arrow [2013-05-08T05:51:43.316458+00:00]> 

104 

105 **One** :class:`Arrow <arrow.arrow.Arrow>` object, to get a copy. 

106 

107 >>> arw = arrow.utcnow() 

108 >>> arrow.get(arw) 

109 <Arrow [2013-10-23T15:21:54.354846+00:00]> 

110 

111 **One** ``float`` or ``int``, convertible to a floating-point timestamp, to get 

112 that timestamp in UTC:: 

113 

114 >>> arrow.get(1367992474.293378) 

115 <Arrow [2013-05-08T05:54:34.293378+00:00]> 

116 

117 >>> arrow.get(1367992474) 

118 <Arrow [2013-05-08T05:54:34+00:00]> 

119 

120 **One** ISO 8601-formatted ``str``, to parse it:: 

121 

122 >>> arrow.get('2013-09-29T01:26:43.830580') 

123 <Arrow [2013-09-29T01:26:43.830580+00:00]> 

124 

125 **One** ISO 8601-formatted ``str``, in basic format, to parse it:: 

126 

127 >>> arrow.get('20160413T133656.456289') 

128 <Arrow [2016-04-13T13:36:56.456289+00:00]> 

129 

130 **One** ``tzinfo``, to get the current time **converted** to that timezone:: 

131 

132 >>> arrow.get(tz.tzlocal()) 

133 <Arrow [2013-05-07T22:57:28.484717-07:00]> 

134 

135 **One** naive ``datetime``, to get that datetime in UTC:: 

136 

137 >>> arrow.get(datetime(2013, 5, 5)) 

138 <Arrow [2013-05-05T00:00:00+00:00]> 

139 

140 **One** aware ``datetime``, to get that datetime:: 

141 

142 >>> arrow.get(datetime(2013, 5, 5, tzinfo=tz.tzlocal())) 

143 <Arrow [2013-05-05T00:00:00-07:00]> 

144 

145 **One** naive ``date``, to get that date in UTC:: 

146 

147 >>> arrow.get(date(2013, 5, 5)) 

148 <Arrow [2013-05-05T00:00:00+00:00]> 

149 

150 **One** time.struct time:: 

151 

152 >>> arrow.get(gmtime(0)) 

153 <Arrow [1970-01-01T00:00:00+00:00]> 

154 

155 **One** iso calendar ``tuple``, to get that week date in UTC:: 

156 

157 >>> arrow.get((2013, 18, 7)) 

158 <Arrow [2013-05-05T00:00:00+00:00]> 

159 

160 **Two** arguments, a naive or aware ``datetime``, and a replacement 

161 :ref:`timezone expression <tz-expr>`:: 

162 

163 >>> arrow.get(datetime(2013, 5, 5), 'US/Pacific') 

164 <Arrow [2013-05-05T00:00:00-07:00]> 

165 

166 **Two** arguments, a naive ``date``, and a replacement 

167 :ref:`timezone expression <tz-expr>`:: 

168 

169 >>> arrow.get(date(2013, 5, 5), 'US/Pacific') 

170 <Arrow [2013-05-05T00:00:00-07:00]> 

171 

172 **Two** arguments, both ``str``, to parse the first according to the format of the second:: 

173 

174 >>> arrow.get('2013-05-05 12:30:45 America/Chicago', 'YYYY-MM-DD HH:mm:ss ZZZ') 

175 <Arrow [2013-05-05T12:30:45-05:00]> 

176 

177 **Two** arguments, first a ``str`` to parse and second a ``list`` of formats to try:: 

178 

179 >>> arrow.get('2013-05-05 12:30:45', ['MM/DD/YYYY', 'YYYY-MM-DD HH:mm:ss']) 

180 <Arrow [2013-05-05T12:30:45+00:00]> 

181 

182 **Three or more** arguments, as for the direct constructor of an ``Arrow`` object:: 

183 

184 >>> arrow.get(2013, 5, 5, 12, 30, 45) 

185 <Arrow [2013-05-05T12:30:45+00:00]> 

186 

187 """ 

188 

189 arg_count = len(args) 

190 locale = kwargs.pop("locale", DEFAULT_LOCALE) 

191 tz = kwargs.get("tzinfo", None) 

192 normalize_whitespace = kwargs.pop("normalize_whitespace", False) 

193 

194 # if kwargs given, send to constructor unless only tzinfo provided 

195 if len(kwargs) > 1: 

196 arg_count = 3 

197 

198 # tzinfo kwarg is not provided 

199 if len(kwargs) == 1 and tz is None: 

200 arg_count = 3 

201 

202 # () -> now, @ tzinfo or utc 

203 if arg_count == 0: 

204 if isinstance(tz, str): 

205 tz = parser.TzinfoParser.parse(tz) 

206 return self.type.now(tzinfo=tz) 

207 

208 if isinstance(tz, dt_tzinfo): 

209 return self.type.now(tzinfo=tz) 

210 

211 return self.type.utcnow() 

212 

213 if arg_count == 1: 

214 arg = args[0] 

215 if isinstance(arg, Decimal): 

216 arg = float(arg) 

217 

218 # (None) -> raises an exception 

219 if arg is None: 

220 raise TypeError("Cannot parse argument of type None.") 

221 

222 # try (int, float) -> from timestamp @ tzinfo 

223 elif not isinstance(arg, str) and is_timestamp(arg): 

224 if tz is None: 

225 # set to UTC by default 

226 tz = timezone.utc 

227 return self.type.fromtimestamp(arg, tzinfo=tz) 

228 

229 # (Arrow) -> from the object's datetime @ tzinfo 

230 elif isinstance(arg, Arrow): 

231 return self.type.fromdatetime(arg.datetime, tzinfo=tz) 

232 

233 # (datetime) -> from datetime @ tzinfo 

234 elif isinstance(arg, datetime): 

235 return self.type.fromdatetime(arg, tzinfo=tz) 

236 

237 # (date) -> from date @ tzinfo 

238 elif isinstance(arg, date): 

239 return self.type.fromdate(arg, tzinfo=tz) 

240 

241 # (tzinfo) -> now @ tzinfo 

242 elif isinstance(arg, dt_tzinfo): 

243 return self.type.now(tzinfo=arg) 

244 

245 # (str) -> parse @ tzinfo 

246 elif isinstance(arg, str): 

247 dt = parser.DateTimeParser(locale).parse_iso(arg, normalize_whitespace) 

248 return self.type.fromdatetime(dt, tzinfo=tz) 

249 

250 # (struct_time) -> from struct_time 

251 elif isinstance(arg, struct_time): 

252 return self.type.utcfromtimestamp(calendar.timegm(arg)) 

253 

254 # (iso calendar) -> convert then from date @ tzinfo 

255 elif isinstance(arg, tuple) and len(arg) == 3: 

256 d = iso_to_gregorian(*arg) 

257 return self.type.fromdate(d, tzinfo=tz) 

258 

259 else: 

260 raise TypeError(f"Cannot parse single argument of type {type(arg)!r}.") 

261 

262 elif arg_count == 2: 

263 arg_1, arg_2 = args[0], args[1] 

264 

265 if isinstance(arg_1, datetime): 

266 # (datetime, tzinfo/str) -> fromdatetime @ tzinfo 

267 if isinstance(arg_2, (dt_tzinfo, str)): 

268 return self.type.fromdatetime(arg_1, tzinfo=arg_2) 

269 else: 

270 raise TypeError( 

271 f"Cannot parse two arguments of types 'datetime', {type(arg_2)!r}." 

272 ) 

273 

274 elif isinstance(arg_1, date): 

275 # (date, tzinfo/str) -> fromdate @ tzinfo 

276 if isinstance(arg_2, (dt_tzinfo, str)): 

277 return self.type.fromdate(arg_1, tzinfo=arg_2) 

278 else: 

279 raise TypeError( 

280 f"Cannot parse two arguments of types 'date', {type(arg_2)!r}." 

281 ) 

282 

283 # (str, format) -> parse @ tzinfo 

284 elif isinstance(arg_1, str) and isinstance(arg_2, (str, list)): 

285 dt = parser.DateTimeParser(locale).parse( 

286 args[0], args[1], normalize_whitespace 

287 ) 

288 return self.type.fromdatetime(dt, tzinfo=tz) 

289 

290 else: 

291 raise TypeError( 

292 f"Cannot parse two arguments of types {type(arg_1)!r} and {type(arg_2)!r}." 

293 ) 

294 

295 # 3+ args -> datetime-like via constructor 

296 else: 

297 return self.type(*args, **kwargs) 

298 

299 def utcnow(self) -> Arrow: 

300 """Returns an :class:`Arrow <arrow.arrow.Arrow>` object, representing "now" in UTC time. 

301 

302 Usage:: 

303 

304 >>> import arrow 

305 >>> arrow.utcnow() 

306 <Arrow [2013-05-08T05:19:07.018993+00:00]> 

307 """ 

308 

309 return self.type.utcnow() 

310 

311 def now(self, tz: Optional[TZ_EXPR] = None) -> Arrow: 

312 """Returns an :class:`Arrow <arrow.arrow.Arrow>` object, representing "now" in the given 

313 timezone. 

314 

315 :param tz: (optional) A :ref:`timezone expression <tz-expr>`. Defaults to local time. 

316 

317 Usage:: 

318 

319 >>> import arrow 

320 >>> arrow.now() 

321 <Arrow [2013-05-07T22:19:11.363410-07:00]> 

322 

323 >>> arrow.now('US/Pacific') 

324 <Arrow [2013-05-07T22:19:15.251821-07:00]> 

325 

326 >>> arrow.now('+02:00') 

327 <Arrow [2013-05-08T07:19:25.618646+02:00]> 

328 

329 >>> arrow.now('local') 

330 <Arrow [2013-05-07T22:19:39.130059-07:00]> 

331 """ 

332 

333 if tz is None: 

334 tz = datetime.now().astimezone().tzinfo 

335 elif not isinstance(tz, dt_tzinfo): 

336 tz = parser.TzinfoParser.parse(tz) 

337 

338 return self.type.now(tz)