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
« 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
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
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 _
34re_formatchars = _lazy_re_compile(r"(?<!\\)([aAbcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])")
35re_escaped = _lazy_re_compile(r"\\(.)")
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)
54class TimeFormat(Formatter):
55 def __init__(self, obj):
56 self.data = obj
57 self.timezone = None
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
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 )
74 def a(self):
75 "'a.m.' or 'p.m.'"
76 if self.data.hour > 11:
77 return _("p.m.")
78 return _("a.m.")
80 def A(self):
81 "'AM' or 'PM'"
82 if self.data.hour > 11:
83 return _("PM")
84 return _("AM")
86 def e(self):
87 """
88 Timezone name.
90 If timezone information is not available, return an empty string.
91 """
92 if not self.timezone:
93 return ""
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 ""
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
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
117 def G(self):
118 "Hour, 24-hour format without leading zeros; i.e. '0' to '23'"
119 return self.data.hour
121 def h(self):
122 "Hour, 12-hour format; i.e. '01' to '12'"
123 return "%02d" % (self.data.hour % 12 or 12)
125 def H(self):
126 "Hour, 24-hour format; i.e. '00' to '23'"
127 return "%02d" % self.data.hour
129 def i(self):
130 "Minutes; i.e. '00' to '59'"
131 return "%02d" % self.data.minute
133 def O(self): # NOQA: E743, E741
134 """
135 Difference to Greenwich time in hours; e.g. '+0200', '-0430'.
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 ""
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)
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())
160 def s(self):
161 "Seconds; i.e. '00' to '59'"
162 return "%02d" % self.data.second
164 def T(self):
165 """
166 Time zone of this machine; e.g. 'EST' or 'MDT'.
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 ""
173 return str(self.timezone.tzname(self.data))
175 def u(self):
176 "Microseconds; i.e. '000000' to '999999'"
177 return "%06d" % self.data.microsecond
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.
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 ""
190 offset = self.timezone.utcoffset(self.data)
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
199class DateFormat(TimeFormat):
200 def b(self):
201 "Month, textual, 3 letters, lowercase; e.g. 'jan'"
202 return MONTHS_3[self.data.month]
204 def c(self):
205 """
206 ISO 8601 Format
207 Example : '2008-01-02T10:30:00.000123'
208 """
209 return self.data.isoformat()
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
215 def D(self):
216 "Day of the week, textual, 3 letters; e.g. 'Fri'"
217 return WEEKDAYS_ABBR[self.data.weekday()]
219 def E(self):
220 "Alternative month names as required by some locales. Proprietary extension."
221 return MONTHS_ALT[self.data.month]
223 def F(self):
224 "Month, textual, long; e.g. 'January'"
225 return MONTHS[self.data.month]
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"
233 def j(self):
234 "Day of the month without leading zeros; i.e. '1' to '31'"
235 return self.data.day
237 def l(self): # NOQA: E743, E741
238 "Day of the week, textual, long; e.g. 'Friday'"
239 return WEEKDAYS[self.data.weekday()]
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)
245 def m(self):
246 "Month; i.e. '01' to '12'"
247 return "%02d" % self.data.month
249 def M(self):
250 "Month, textual, 3 letters; e.g. 'Jan'"
251 return MONTHS_3[self.data.month].title()
253 def n(self):
254 "Month without leading zeros; i.e. '1' to '12'"
255 return self.data.month
257 def N(self):
258 "Month abbreviation in Associated Press style. Proprietary extension."
259 return MONTHS_AP[self.data.month]
261 def o(self):
262 "ISO 8601 year number matching the ISO week number (W)"
263 return self.data.isocalendar()[0]
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)
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"
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]
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())
305 def w(self):
306 "Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)"
307 return (self.data.weekday() + 1) % 7
309 def W(self):
310 "ISO-8601 week number of year, weeks starting on Monday"
311 return self.data.isocalendar()[1]
313 def y(self):
314 """Year, 2 digits with leading zeros; e.g. '99'."""
315 return "%02d" % (self.data.year % 100)
317 def Y(self):
318 """Year, 4 digits with leading zeros; e.g. '1999'."""
319 return "%04d" % self.data.year
321 def z(self):
322 """Day of the year, i.e. 1 to 366."""
323 return self.data.timetuple().tm_yday
326def format(value, format_string):
327 "Convenience function"
328 df = DateFormat(value)
329 return df.format(format_string)
332def time_format(value, format_string):
333 "Convenience function"
334 tf = TimeFormat(value)
335 return tf.format(format_string)