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

1""" 

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

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

4construction scenarios. 

5 

6""" 

7 

8 

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 

15 

16from dateutil import tz as dateutil_tz 

17 

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 

22 

23 

24class ArrowFactory: 

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

26 

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

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

29 

30 """ 

31 

32 type: Type[Arrow] 

33 

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

35 self.type = type 

36 

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 

46 

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 

67 

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 

79 

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 

91 

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

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

94 

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. 

102 

103 Usage:: 

104 

105 >>> import arrow 

106 

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

108 

109 >>> arrow.get() 

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

111 

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

113 

114 >>> arw = arrow.utcnow() 

115 >>> arrow.get(arw) 

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

117 

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

119 that timestamp in UTC:: 

120 

121 >>> arrow.get(1367992474.293378) 

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

123 

124 >>> arrow.get(1367992474) 

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

126 

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

128 

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

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

131 

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

133 

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

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

136 

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

138 

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

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

141 

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

143 

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

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

146 

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

148 

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

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

151 

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

153 

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

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

156 

157 **One** time.struct time:: 

158 

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

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

161 

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

163 

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

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

166 

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

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

169 

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

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

172 

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

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

175 

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

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

178 

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

180 

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]> 

183 

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

185 

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]> 

188 

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

190 

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

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

193 

194 """ 

195 

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) 

200 

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

202 if len(kwargs) > 1: 

203 arg_count = 3 

204 

205 # tzinfo kwarg is not provided 

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

207 arg_count = 3 

208 

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) 

214 

215 if isinstance(tz, dt_tzinfo): 

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

217 

218 return self.type.utcnow() 

219 

220 if arg_count == 1: 

221 arg = args[0] 

222 if isinstance(arg, Decimal): 

223 arg = float(arg) 

224 

225 # (None) -> raises an exception 

226 if arg is None: 

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

228 

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) 

235 

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

237 elif isinstance(arg, Arrow): 

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

239 

240 # (datetime) -> from datetime @ tzinfo 

241 elif isinstance(arg, datetime): 

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

243 

244 # (date) -> from date @ tzinfo 

245 elif isinstance(arg, date): 

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

247 

248 # (tzinfo) -> now @ tzinfo 

249 elif isinstance(arg, dt_tzinfo): 

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

251 

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) 

256 

257 # (struct_time) -> from struct_time 

258 elif isinstance(arg, struct_time): 

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

260 

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) 

265 

266 else: 

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

268 

269 elif arg_count == 2: 

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

271 

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 ) 

280 

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 ) 

289 

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) 

296 

297 else: 

298 raise TypeError( 

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

300 ) 

301 

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

303 else: 

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

305 

306 def utcnow(self) -> Arrow: 

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

308 

309 Usage:: 

310 

311 >>> import arrow 

312 >>> arrow.utcnow() 

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

314 """ 

315 

316 return self.type.utcnow() 

317 

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. 

321 

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

323 

324 Usage:: 

325 

326 >>> import arrow 

327 >>> arrow.now() 

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

329 

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

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

332 

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

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

335 

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

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

338 """ 

339 

340 if tz is None: 

341 tz = dateutil_tz.tzlocal() 

342 elif not isinstance(tz, dt_tzinfo): 

343 tz = parser.TzinfoParser.parse(tz) 

344 

345 return self.type.now(tz)