2 PHP date() style date formatting
3 See http://www.php.net/date for format strings
7 >>> d = datetime.datetime.now()
9 >>> print df.format('jS F Y H:i')
10 7th October 2003 11:39
14 from django
.utils
.dates
import MONTHS
, MONTHS_AP
, WEEKDAYS
15 from django
.utils
.tzinfo
import LocalTimezone
16 from calendar
import isleap
, monthrange
19 re_formatchars
= re
.compile(r
'(?<!\\)([aABdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])')
20 re_escaped
= re
.compile(r
'\\(.)')
23 def format(self
, formatstr
):
25 for i
, piece
in enumerate(re_formatchars
.split(formatstr
)):
27 pieces
.append(str(getattr(self
, piece
)()))
29 pieces
.append(re_escaped
.sub(r
'\1', piece
))
30 return ''.join(pieces
)
32 class TimeFormat(Formatter
):
33 def __init__(self
, t
):
38 if self
.data
.hour
> 11:
44 if self
.data
.hour
> 11:
49 "Swatch Internet time"
50 raise NotImplementedError
54 Time, in 12-hour hours and minutes, with minutes left off if they're zero.
55 Examples: '1', '1:30', '2:05', '2'
56 Proprietary extension.
58 if self
.data
.minute
== 0:
60 return '%s:%s' % (self
.g(), self
.i())
63 "Hour, 12-hour format without leading zeros; i.e. '1' to '12'"
64 if self
.data
.hour
== 0:
66 if self
.data
.hour
> 12:
67 return self
.data
.hour
- 12
71 "Hour, 24-hour format without leading zeros; i.e. '0' to '23'"
75 "Hour, 12-hour format; i.e. '01' to '12'"
76 return '%02d' % self
.g()
79 "Hour, 24-hour format; i.e. '00' to '23'"
80 return '%02d' % self
.G()
83 "Minutes; i.e. '00' to '59'"
84 return '%02d' % self
.data
.minute
88 Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
89 if they're zero and the strings 'midnight' and 'noon' if appropriate.
90 Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.'
91 Proprietary extension.
93 if self
.data
.minute
== 0 and self
.data
.hour
== 0:
95 if self
.data
.minute
== 0 and self
.data
.hour
== 12:
97 return '%s %s' % (self
.f(), self
.a())
100 "Seconds; i.e. '00' to '59'"
101 return '%02d' % self
.data
.second
103 class DateFormat(TimeFormat
):
104 year_days
= [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
106 def __init__(self
, dt
):
107 # Accepts either a datetime or date object.
109 self
.timezone
= getattr(dt
, 'tzinfo', None)
110 if hasattr(self
.data
, 'hour') and not self
.timezone
:
111 self
.timezone
= LocalTimezone(dt
)
114 "Day of the month, 2 digits with leading zeros; i.e. '01' to '31'"
115 return '%02d' % self
.data
.day
118 "Day of the week, textual, 3 letters; e.g. 'Fri'"
119 return WEEKDAYS
[self
.data
.weekday()][0:3]
122 "Month, textual, long; e.g. 'January'"
123 return MONTHS
[self
.data
.month
]
126 "'1' if Daylight Savings Time, '0' otherwise."
127 if self
.timezone
.dst(self
.data
):
133 "Day of the month without leading zeros; i.e. '1' to '31'"
137 "Day of the week, textual, long; e.g. 'Friday'"
138 return WEEKDAYS
[self
.data
.weekday()]
141 "Boolean for whether it is a leap year; i.e. True or False"
142 return isleap(self
.data
.year
)
145 "Month; i.e. '01' to '12'"
146 return '%02d' % self
.data
.month
149 "Month, textual, 3 letters; e.g. 'Jan'"
150 return MONTHS
[self
.data
.month
][0:3]
153 "Month without leading zeros; i.e. '1' to '12'"
154 return self
.data
.month
157 "Month abbreviation in Associated Press style. Proprietary extension."
158 return MONTHS_AP
[self
.data
.month
]
161 "Difference to Greenwich time in hours; e.g. '+0200'"
162 tz
= self
.timezone
.utcoffset(self
.data
)
163 return "%+03d%02d" % (tz
.seconds
// 3600, (tz
.seconds
// 60) % 60)
166 "RFC 822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'"
167 return self
.format('D, j M Y H:i:s O')
170 "English ordinal suffix for the day of the month, 2 characters; i.e. 'st', 'nd', 'rd' or 'th'"
171 if self
.data
.day
in (11, 12, 13): # Special case
173 last
= self
.data
.day
% 10
183 "Number of days in the given month; i.e. '28' to '31'"
184 return '%02d' % monthrange(self
.data
.year
, self
.data
.month
)[1]
187 "Time zone of this machine; e.g. 'EST' or 'MDT'"
188 name
= self
.timezone
.tzname(self
.data
)
190 name
= self
.format('O')
194 "Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)"
195 off
= self
.timezone
.utcoffset(self
.data
)
196 return int(time
.mktime(self
.data
.timetuple())) + off
.seconds
* 60
199 "Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)"
200 return (self
.data
.weekday() + 1) % 7
203 "ISO-8601 week number of year, weeks starting on Monday"
204 # Algorithm from http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt
206 jan1_weekday
= self
.data
.replace(month
=1, day
=1).weekday() + 1
207 weekday
= self
.data
.weekday() + 1
208 day_of_year
= self
.z()
209 if day_of_year
<= (8 - jan1_weekday
) and jan1_weekday
> 4:
210 if jan1_weekday
== 5 or (jan1_weekday
== 6 and isleap(self
.data
.year
-1)):
215 if isleap(self
.data
.year
):
219 if (i
- day_of_year
) < (4 - weekday
):
222 j
= day_of_year
+ (7 - weekday
) + (jan1_weekday
- 1)
229 "Year, 2 digits; e.g. '99'"
230 return str(self
.data
.year
)[2:]
233 "Year, 4 digits; e.g. '1999'"
234 return self
.data
.year
237 "Day of the year; i.e. '0' to '365'"
238 doy
= self
.year_days
[self
.data
.month
] + self
.data
.day
239 if self
.L() and self
.data
.month
> 2:
244 """Time zone offset in seconds (i.e. '-43200' to '43200'). The offset
245 for timezones west of UTC is always negative, and for those east of UTC
246 is always positive."""
247 return self
.timezone
.utcoffset(self
.data
).seconds
249 def format(value
, format_string
):
250 "Convenience function"
251 df
= DateFormat(value
)
252 return df
.format(format_string
)
254 def time_format(value
, format_string
):
255 "Convenience function"
256 tf
= TimeFormat(value
)
257 return tf
.format(format_string
)