Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/utils/dateformat.py: 29%

162 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1""" 

2PHP date() style date formatting 

3See http://www.php.net/date for format strings 

4 

5Usage: 

6>>> import datetime 

7>>> d = datetime.datetime.now() 

8>>> df = DateFormat(d) 

9>>> print(df.format('jS F Y H:i')) 

107th October 2003 11:39 

11>>> 

12""" 

13import calendar 

14import datetime 

15from email.utils import format_datetime as format_datetime_rfc5322 

16 

17from django.utils.dates import ( 

18 MONTHS, 

19 MONTHS_3, 

20 MONTHS_ALT, 

21 MONTHS_AP, 

22 WEEKDAYS, 

23 WEEKDAYS_ABBR, 

24) 

25from django.utils.regex_helper import _lazy_re_compile 

26from django.utils.timezone import ( 

27 _datetime_ambiguous_or_imaginary, 

28 get_default_timezone, 

29 is_naive, 

30 make_aware, 

31) 

32from django.utils.translation import gettext as _ 

33 

34re_formatchars = _lazy_re_compile(r"(?<!\\)([aAbcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])") 

35re_escaped = _lazy_re_compile(r"\\(.)") 

36 

37 

38class Formatter: 

39 def format(self, formatstr): 

40 pieces = [] 

41 for i, piece in enumerate(re_formatchars.split(str(formatstr))): 

42 if i % 2: 

43 if type(self.data) is datetime.date and hasattr(TimeFormat, piece): 

44 raise TypeError( 

45 "The format for date objects may not contain " 

46 "time-related format specifiers (found '%s')." % piece 

47 ) 

48 pieces.append(str(getattr(self, piece)())) 

49 elif piece: 

50 pieces.append(re_escaped.sub(r"\1", piece)) 

51 return "".join(pieces) 

52 

53 

54class TimeFormat(Formatter): 

55 def __init__(self, obj): 

56 self.data = obj 

57 self.timezone = None 

58 

59 # We only support timezone when formatting datetime objects, 

60 # not date objects (timezone information not appropriate), 

61 # or time objects (against established django policy). 

62 if isinstance(obj, datetime.datetime): 

63 if is_naive(obj): 

64 self.timezone = get_default_timezone() 

65 else: 

66 self.timezone = obj.tzinfo 

67 

68 @property 

69 def _no_timezone_or_datetime_is_ambiguous_or_imaginary(self): 

70 return not self.timezone or _datetime_ambiguous_or_imaginary( 

71 self.data, self.timezone 

72 ) 

73 

74 def a(self): 

75 "'a.m.' or 'p.m.'" 

76 if self.data.hour > 11: 

77 return _("p.m.") 

78 return _("a.m.") 

79 

80 def A(self): 

81 "'AM' or 'PM'" 

82 if self.data.hour > 11: 

83 return _("PM") 

84 return _("AM") 

85 

86 def e(self): 

87 """ 

88 Timezone name. 

89 

90 If timezone information is not available, return an empty string. 

91 """ 

92 if not self.timezone: 

93 return "" 

94 

95 try: 

96 if hasattr(self.data, "tzinfo") and self.data.tzinfo: 

97 return self.data.tzname() or "" 

98 except NotImplementedError: 

99 pass 

100 return "" 

101 

102 def f(self): 

103 """ 

104 Time, in 12-hour hours and minutes, with minutes left off if they're 

105 zero. 

106 Examples: '1', '1:30', '2:05', '2' 

107 Proprietary extension. 

108 """ 

109 hour = self.data.hour % 12 or 12 

110 minute = self.data.minute 

111 return "%d:%02d" % (hour, minute) if minute else hour 

112 

113 def g(self): 

114 "Hour, 12-hour format without leading zeros; i.e. '1' to '12'" 

115 return self.data.hour % 12 or 12 

116 

117 def G(self): 

118 "Hour, 24-hour format without leading zeros; i.e. '0' to '23'" 

119 return self.data.hour 

120 

121 def h(self): 

122 "Hour, 12-hour format; i.e. '01' to '12'" 

123 return "%02d" % (self.data.hour % 12 or 12) 

124 

125 def H(self): 

126 "Hour, 24-hour format; i.e. '00' to '23'" 

127 return "%02d" % self.data.hour 

128 

129 def i(self): 

130 "Minutes; i.e. '00' to '59'" 

131 return "%02d" % self.data.minute 

132 

133 def O(self): # NOQA: E743, E741 

134 """ 

135 Difference to Greenwich time in hours; e.g. '+0200', '-0430'. 

136 

137 If timezone information is not available, return an empty string. 

138 """ 

139 if self._no_timezone_or_datetime_is_ambiguous_or_imaginary: 

140 return "" 

141 

142 seconds = self.Z() 

143 sign = "-" if seconds < 0 else "+" 

144 seconds = abs(seconds) 

145 return "%s%02d%02d" % (sign, seconds // 3600, (seconds // 60) % 60) 

146 

147 def P(self): 

148 """ 

149 Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off 

150 if they're zero and the strings 'midnight' and 'noon' if appropriate. 

151 Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.' 

152 Proprietary extension. 

153 """ 

154 if self.data.minute == 0 and self.data.hour == 0: 

155 return _("midnight") 

156 if self.data.minute == 0 and self.data.hour == 12: 

157 return _("noon") 

158 return "%s %s" % (self.f(), self.a()) 

159 

160 def s(self): 

161 "Seconds; i.e. '00' to '59'" 

162 return "%02d" % self.data.second 

163 

164 def T(self): 

165 """ 

166 Time zone of this machine; e.g. 'EST' or 'MDT'. 

167 

168 If timezone information is not available, return an empty string. 

169 """ 

170 if self._no_timezone_or_datetime_is_ambiguous_or_imaginary: 

171 return "" 

172 

173 return str(self.timezone.tzname(self.data)) 

174 

175 def u(self): 

176 "Microseconds; i.e. '000000' to '999999'" 

177 return "%06d" % self.data.microsecond 

178 

179 def Z(self): 

180 """ 

181 Time zone offset in seconds (i.e. '-43200' to '43200'). The offset for 

182 timezones west of UTC is always negative, and for those east of UTC is 

183 always positive. 

184 

185 If timezone information is not available, return an empty string. 

186 """ 

187 if self._no_timezone_or_datetime_is_ambiguous_or_imaginary: 

188 return "" 

189 

190 offset = self.timezone.utcoffset(self.data) 

191 

192 # `offset` is a datetime.timedelta. For negative values (to the west of 

193 # UTC) only days can be negative (days=-1) and seconds are always 

194 # positive. e.g. UTC-1 -> timedelta(days=-1, seconds=82800, microseconds=0) 

195 # Positive offsets have days=0 

196 return offset.days * 86400 + offset.seconds 

197 

198 

199class DateFormat(TimeFormat): 

200 def b(self): 

201 "Month, textual, 3 letters, lowercase; e.g. 'jan'" 

202 return MONTHS_3[self.data.month] 

203 

204 def c(self): 

205 """ 

206 ISO 8601 Format 

207 Example : '2008-01-02T10:30:00.000123' 

208 """ 

209 return self.data.isoformat() 

210 

211 def d(self): 

212 "Day of the month, 2 digits with leading zeros; i.e. '01' to '31'" 

213 return "%02d" % self.data.day 

214 

215 def D(self): 

216 "Day of the week, textual, 3 letters; e.g. 'Fri'" 

217 return WEEKDAYS_ABBR[self.data.weekday()] 

218 

219 def E(self): 

220 "Alternative month names as required by some locales. Proprietary extension." 

221 return MONTHS_ALT[self.data.month] 

222 

223 def F(self): 

224 "Month, textual, long; e.g. 'January'" 

225 return MONTHS[self.data.month] 

226 

227 def I(self): # NOQA: E743, E741 

228 "'1' if daylight saving time, '0' otherwise." 

229 if self._no_timezone_or_datetime_is_ambiguous_or_imaginary: 

230 return "" 

231 return "1" if self.timezone.dst(self.data) else "0" 

232 

233 def j(self): 

234 "Day of the month without leading zeros; i.e. '1' to '31'" 

235 return self.data.day 

236 

237 def l(self): # NOQA: E743, E741 

238 "Day of the week, textual, long; e.g. 'Friday'" 

239 return WEEKDAYS[self.data.weekday()] 

240 

241 def L(self): 

242 "Boolean for whether it is a leap year; i.e. True or False" 

243 return calendar.isleap(self.data.year) 

244 

245 def m(self): 

246 "Month; i.e. '01' to '12'" 

247 return "%02d" % self.data.month 

248 

249 def M(self): 

250 "Month, textual, 3 letters; e.g. 'Jan'" 

251 return MONTHS_3[self.data.month].title() 

252 

253 def n(self): 

254 "Month without leading zeros; i.e. '1' to '12'" 

255 return self.data.month 

256 

257 def N(self): 

258 "Month abbreviation in Associated Press style. Proprietary extension." 

259 return MONTHS_AP[self.data.month] 

260 

261 def o(self): 

262 "ISO 8601 year number matching the ISO week number (W)" 

263 return self.data.isocalendar()[0] 

264 

265 def r(self): 

266 "RFC 5322 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'" 

267 if type(self.data) is datetime.date: 

268 raise TypeError( 

269 "The format for date objects may not contain time-related " 

270 "format specifiers (found 'r')." 

271 ) 

272 if is_naive(self.data): 

273 dt = make_aware(self.data, timezone=self.timezone) 

274 else: 

275 dt = self.data 

276 return format_datetime_rfc5322(dt) 

277 

278 def S(self): 

279 """ 

280 English ordinal suffix for the day of the month, 2 characters; i.e. 

281 'st', 'nd', 'rd' or 'th'. 

282 """ 

283 if self.data.day in (11, 12, 13): # Special case 

284 return "th" 

285 last = self.data.day % 10 

286 if last == 1: 

287 return "st" 

288 if last == 2: 

289 return "nd" 

290 if last == 3: 

291 return "rd" 

292 return "th" 

293 

294 def t(self): 

295 "Number of days in the given month; i.e. '28' to '31'" 

296 return "%02d" % calendar.monthrange(self.data.year, self.data.month)[1] 

297 

298 def U(self): 

299 "Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)" 

300 value = self.data 

301 if not isinstance(value, datetime.datetime): 

302 value = datetime.datetime.combine(value, datetime.time.min) 

303 return int(value.timestamp()) 

304 

305 def w(self): 

306 "Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)" 

307 return (self.data.weekday() + 1) % 7 

308 

309 def W(self): 

310 "ISO-8601 week number of year, weeks starting on Monday" 

311 return self.data.isocalendar()[1] 

312 

313 def y(self): 

314 """Year, 2 digits with leading zeros; e.g. '99'.""" 

315 return "%02d" % (self.data.year % 100) 

316 

317 def Y(self): 

318 """Year, 4 digits with leading zeros; e.g. '1999'.""" 

319 return "%04d" % self.data.year 

320 

321 def z(self): 

322 """Day of the year, i.e. 1 to 366.""" 

323 return self.data.timetuple().tm_yday 

324 

325 

326def format(value, format_string): 

327 "Convenience function" 

328 df = DateFormat(value) 

329 return df.format(format_string) 

330 

331 

332def time_format(value, format_string): 

333 "Convenience function" 

334 tf = TimeFormat(value) 

335 return tf.format(format_string)