Django

Code

root/django/trunk/django/utils/dateformat.py

Revision 8046, 8.2 kB (checked in by adrian, 4 months ago)

Fixed #7847 -- Removed a whole bunch of unused imports from throughout the codebase. Thanks, julien

  • Property svn:eol-style set to native
  • Property svn:keywords set to LastChangedRevision
Line 
1 """
2 PHP date() style date formatting
3 See http://www.php.net/date for format strings
4
5 Usage:
6 >>> import datetime
7 >>> d = datetime.datetime.now()
8 >>> df = DateFormat(d)
9 >>> print df.format('jS F Y H:i')
10 7th October 2003 11:39
11 >>>
12 """
13
14 from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS, WEEKDAYS_ABBR
15 from django.utils.tzinfo import LocalTimezone
16 from django.utils.translation import ugettext as _
17 from django.utils.encoding import force_unicode
18 from calendar import isleap, monthrange
19 import re, time
20
21 re_formatchars = re.compile(r'(?<!\\)([aAbBdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])')
22 re_escaped = re.compile(r'\\(.)')
23
24 class Formatter(object):
25     def format(self, formatstr):
26         pieces = []
27         for i, piece in enumerate(re_formatchars.split(force_unicode(formatstr))):
28             if i % 2:
29                 pieces.append(force_unicode(getattr(self, piece)()))
30             elif piece:
31                 pieces.append(re_escaped.sub(r'\1', piece))
32         return u''.join(pieces)
33
34 class TimeFormat(Formatter):
35     def __init__(self, t):
36         self.data = t
37
38     def a(self):
39         "'a.m.' or 'p.m.'"
40         if self.data.hour > 11:
41             return _('p.m.')
42         return _('a.m.')
43
44     def A(self):
45         "'AM' or 'PM'"
46         if self.data.hour > 11:
47             return _('PM')
48         return _('AM')
49
50     def B(self):
51         "Swatch Internet time"
52         raise NotImplementedError
53
54     def f(self):
55         """
56         Time, in 12-hour hours and minutes, with minutes left off if they're
57         zero.
58         Examples: '1', '1:30', '2:05', '2'
59         Proprietary extension.
60         """
61         if self.data.minute == 0:
62             return self.g()
63         return u'%s:%s' % (self.g(), self.i())
64
65     def g(self):
66         "Hour, 12-hour format without leading zeros; i.e. '1' to '12'"
67         if self.data.hour == 0:
68             return 12
69         if self.data.hour > 12:
70             return self.data.hour - 12
71         return self.data.hour
72
73     def G(self):
74         "Hour, 24-hour format without leading zeros; i.e. '0' to '23'"
75         return self.data.hour
76
77     def h(self):
78         "Hour, 12-hour format; i.e. '01' to '12'"
79         return u'%02d' % self.g()
80
81     def H(self):
82         "Hour, 24-hour format; i.e. '00' to '23'"
83         return u'%02d' % self.G()
84
85     def i(self):
86         "Minutes; i.e. '00' to '59'"
87         return u'%02d' % self.data.minute
88
89     def P(self):
90         """
91         Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
92         if they're zero and the strings 'midnight' and 'noon' if appropriate.
93         Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
94         Proprietary extension.
95         """
96         if self.data.minute == 0 and self.data.hour == 0:
97             return _('midnight')
98         if self.data.minute == 0 and self.data.hour == 12:
99             return _('noon')
100         return u'%s %s' % (self.f(), self.a())
101
102     def s(self):
103         "Seconds; i.e. '00' to '59'"
104         return u'%02d' % self.data.second
105
106 class DateFormat(TimeFormat):
107     year_days = [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
108
109     def __init__(self, dt):
110         # Accepts either a datetime or date object.
111         self.data = dt
112         self.timezone = getattr(dt, 'tzinfo', None)
113         if hasattr(self.data, 'hour') and not self.timezone:
114             self.timezone = LocalTimezone(dt)
115
116     def b(self):
117         "Month, textual, 3 letters, lowercase; e.g. 'jan'"
118         return MONTHS_3[self.data.month]
119
120     def d(self):
121         "Day of the month, 2 digits with leading zeros; i.e. '01' to '31'"
122         return u'%02d' % self.data.day
123
124     def D(self):
125         "Day of the week, textual, 3 letters; e.g. 'Fri'"
126         return WEEKDAYS_ABBR[self.data.weekday()]
127
128     def F(self):
129         "Month, textual, long; e.g. 'January'"
130         return MONTHS[self.data.month]
131
132     def I(self):
133         "'1' if Daylight Savings Time, '0' otherwise."
134         if self.timezone.dst(self.data):
135             return u'1'
136         else:
137             return u'0'
138
139     def j(self):
140         "Day of the month without leading zeros; i.e. '1' to '31'"
141         return self.data.day
142
143     def l(self):
144         "Day of the week, textual, long; e.g. 'Friday'"
145         return WEEKDAYS[self.data.weekday()]
146
147     def L(self):
148         "Boolean for whether it is a leap year; i.e. True or False"
149         return isleap(self.data.year)
150
151     def m(self):
152         "Month; i.e. '01' to '12'"
153         return u'%02d' % self.data.month
154
155     def M(self):
156         "Month, textual, 3 letters; e.g. 'Jan'"
157         return MONTHS_3[self.data.month].title()
158
159     def n(self):
160         "Month without leading zeros; i.e. '1' to '12'"
161         return self.data.month
162
163     def N(self):
164         "Month abbreviation in Associated Press style. Proprietary extension."
165         return MONTHS_AP[self.data.month]
166
167     def O(self):
168         "Difference to Greenwich time in hours; e.g. '+0200'"
169         seconds = self.Z()
170         return u"%+03d%02d" % (seconds // 3600, (seconds // 60) % 60)
171
172     def r(self):
173         "RFC 2822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'"
174         return self.format('D, j M Y H:i:s O')
175
176     def S(self):
177         "English ordinal suffix for the day of the month, 2 characters; i.e. 'st', 'nd', 'rd' or 'th'"
178         if self.data.day in (11, 12, 13): # Special case
179             return u'th'
180         last = self.data.day % 10
181         if last == 1:
182             return u'st'
183         if last == 2:
184             return u'nd'
185         if last == 3:
186             return u'rd'
187         return u'th'
188
189     def t(self):
190         "Number of days in the given month; i.e. '28' to '31'"
191         return u'%02d' % monthrange(self.data.year, self.data.month)[1]
192
193     def T(self):
194         "Time zone of this machine; e.g. 'EST' or 'MDT'"
195         name = self.timezone.tzname(self.data)
196         if name is None:
197             name = self.format('O')
198         return unicode(name)
199
200     def U(self):
201         "Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)"
202         off = self.timezone.utcoffset(self.data)
203         return int(time.mktime(self.data.timetuple())) + off.seconds * 60
204
205     def w(self):
206         "Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)"
207         return (self.data.weekday() + 1) % 7
208
209     def W(self):
210         "ISO-8601 week number of year, weeks starting on Monday"
211         # Algorithm from http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt
212         week_number = None
213         jan1_weekday = self.data.replace(month=1, day=1).weekday() + 1
214         weekday = self.data.weekday() + 1
215         day_of_year = self.z()
216         if day_of_year <= (8 - jan1_weekday) and jan1_weekday > 4:
217             if jan1_weekday == 5 or (jan1_weekday == 6 and isleap(self.data.year-1)):
218                 week_number = 53
219             else:
220                 week_number = 52
221         else:
222             if isleap(self.data.year):
223                 i = 366
224             else:
225                 i = 365
226             if (i - day_of_year) < (4 - weekday):
227                 week_number = 1
228             else:
229                 j = day_of_year + (7 - weekday) + (jan1_weekday - 1)
230                 week_number = j // 7
231                 if jan1_weekday > 4:
232                     week_number -= 1
233         return week_number
234
235     def y(self):
236         "Year, 2 digits; e.g. '99'"
237         return unicode(self.data.year)[2:]
238
239     def Y(self):
240         "Year, 4 digits; e.g. '1999'"
241         return self.data.year
242
243     def z(self):
244         "Day of the year; i.e. '0' to '365'"
245         doy = self.year_days[self.data.month] + self.data.day
246         if self.L() and self.data.month > 2:
247             doy += 1
248         return doy
249
250     def Z(self):
251         """
252         Time zone offset in seconds (i.e. '-43200' to '43200'). The offset for
253         timezones west of UTC is always negative, and for those east of UTC is
254         always positive.
255         """
256         offset = self.timezone.utcoffset(self.data)
257         # Only days can be negative, so negative offsets have days=-1 and
258         # seconds positive. Positive offsets have days=0
259         return offset.days * 86400 + offset.seconds
260
261 def format(value, format_string):
262     "Convenience function"
263     df = DateFormat(value)
264     return df.format(format_string)
265
266 def time_format(value, format_string):
267     "Convenience function"
268     tf = TimeFormat(value)
269     return tf.format(format_string)
Note: See TracBrowser for help on using the browser.