Mercurial > babel > old > babel-test
annotate babel/dates.py @ 518:9d6fa3d28473
Change occurence of 'metainfo' to 'metazone_info'. 'metainfo' was not
used anywhere and the test was made against 'metazone_info', similar to the
'info' test above.
author | jruigrok |
---|---|
date | Sat, 05 Mar 2011 09:59:28 +0000 |
parents | 606af7395ad8 |
children | 85e1beadacb0 |
rev | line source |
---|---|
1 | 1 # -*- coding: utf-8 -*- |
2 # | |
3 # Copyright (C) 2007 Edgewall Software | |
4 # All rights reserved. | |
5 # | |
6 # This software is licensed as described in the file COPYING, which | |
7 # you should have received as part of this distribution. The terms | |
8 # are also available at http://babel.edgewall.org/wiki/License. | |
9 # | |
10 # This software consists of voluntary contributions made by many | |
11 # individuals. For the exact contribution history, see the revision | |
12 # history and logs, available at http://babel.edgewall.org/log/. | |
13 | |
14 """Locale dependent formatting and parsing of dates and times. | |
15 | |
16 The default locale for the functions in this module is determined by the | |
17 following environment variables, in that order: | |
18 | |
19 * ``LC_TIME``, | |
20 * ``LC_ALL``, and | |
21 * ``LANG`` | |
22 """ | |
23 | |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
24 from __future__ import division |
515 | 25 from datetime import date, datetime, time, timedelta |
38
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
26 import re |
1 | 27 |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
28 from babel.core import default_locale, get_global, Locale |
39
3b314a78015d
Move function for determining the system default locale to `babel.core`, and make it available as a class method on `Locale`.
cmlenz
parents:
38
diff
changeset
|
29 from babel.util import UTC |
1 | 30 |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
31 __all__ = ['format_date', 'format_datetime', 'format_time', 'format_timedelta', |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
32 'get_timezone_name', 'parse_date', 'parse_datetime', 'parse_time'] |
1 | 33 __docformat__ = 'restructuredtext en' |
34 | |
72
4dcdb1d367ec
More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents:
46
diff
changeset
|
35 LC_TIME = default_locale('LC_TIME') |
1 | 36 |
33 | 37 # Aliases for use in scopes where the modules are shadowed by local variables |
38 date_ = date | |
39 datetime_ = datetime | |
40 time_ = time | |
41 | |
1 | 42 def get_period_names(locale=LC_TIME): |
43 """Return the names for day periods (AM/PM) used by the locale. | |
44 | |
45 >>> get_period_names(locale='en_US')['am'] | |
46 u'AM' | |
47 | |
48 :param locale: the `Locale` object, or a locale string | |
49 :return: the dictionary of period names | |
50 :rtype: `dict` | |
51 """ | |
52 return Locale.parse(locale).periods | |
53 | |
54 def get_day_names(width='wide', context='format', locale=LC_TIME): | |
55 """Return the day names used by the locale for the specified format. | |
56 | |
57 >>> get_day_names('wide', locale='en_US')[1] | |
15 | 58 u'Tuesday' |
1 | 59 >>> get_day_names('abbreviated', locale='es')[1] |
15 | 60 u'mar' |
1 | 61 >>> get_day_names('narrow', context='stand-alone', locale='de_DE')[1] |
15 | 62 u'D' |
1 | 63 |
64 :param width: the width to use, one of "wide", "abbreviated", or "narrow" | |
65 :param context: the context, either "format" or "stand-alone" | |
66 :param locale: the `Locale` object, or a locale string | |
67 :return: the dictionary of day names | |
68 :rtype: `dict` | |
69 """ | |
70 return Locale.parse(locale).days[context][width] | |
71 | |
72 def get_month_names(width='wide', context='format', locale=LC_TIME): | |
73 """Return the month names used by the locale for the specified format. | |
74 | |
75 >>> get_month_names('wide', locale='en_US')[1] | |
76 u'January' | |
77 >>> get_month_names('abbreviated', locale='es')[1] | |
78 u'ene' | |
79 >>> get_month_names('narrow', context='stand-alone', locale='de_DE')[1] | |
80 u'J' | |
81 | |
82 :param width: the width to use, one of "wide", "abbreviated", or "narrow" | |
83 :param context: the context, either "format" or "stand-alone" | |
84 :param locale: the `Locale` object, or a locale string | |
85 :return: the dictionary of month names | |
86 :rtype: `dict` | |
87 """ | |
88 return Locale.parse(locale).months[context][width] | |
89 | |
90 def get_quarter_names(width='wide', context='format', locale=LC_TIME): | |
91 """Return the quarter names used by the locale for the specified format. | |
92 | |
93 >>> get_quarter_names('wide', locale='en_US')[1] | |
94 u'1st quarter' | |
95 >>> get_quarter_names('abbreviated', locale='de_DE')[1] | |
96 u'Q1' | |
97 | |
98 :param width: the width to use, one of "wide", "abbreviated", or "narrow" | |
99 :param context: the context, either "format" or "stand-alone" | |
100 :param locale: the `Locale` object, or a locale string | |
101 :return: the dictionary of quarter names | |
102 :rtype: `dict` | |
103 """ | |
104 return Locale.parse(locale).quarters[context][width] | |
105 | |
106 def get_era_names(width='wide', locale=LC_TIME): | |
107 """Return the era names used by the locale for the specified format. | |
108 | |
109 >>> get_era_names('wide', locale='en_US')[1] | |
110 u'Anno Domini' | |
111 >>> get_era_names('abbreviated', locale='de_DE')[1] | |
112 u'n. Chr.' | |
113 | |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
114 :param width: the width to use, either "wide", "abbreviated", or "narrow" |
1 | 115 :param locale: the `Locale` object, or a locale string |
116 :return: the dictionary of era names | |
117 :rtype: `dict` | |
118 """ | |
119 return Locale.parse(locale).eras[width] | |
120 | |
121 def get_date_format(format='medium', locale=LC_TIME): | |
122 """Return the date formatting patterns used by the locale for the specified | |
123 format. | |
124 | |
125 >>> get_date_format(locale='en_US') | |
430 | 126 <DateTimePattern u'MMM d, y'> |
1 | 127 >>> get_date_format('full', locale='de_DE') |
430 | 128 <DateTimePattern u'EEEE, d. MMMM y'> |
1 | 129 |
130 :param format: the format to use, one of "full", "long", "medium", or | |
131 "short" | |
132 :param locale: the `Locale` object, or a locale string | |
133 :return: the date format pattern | |
33 | 134 :rtype: `DateTimePattern` |
1 | 135 """ |
136 return Locale.parse(locale).date_formats[format] | |
137 | |
33 | 138 def get_datetime_format(format='medium', locale=LC_TIME): |
139 """Return the datetime formatting patterns used by the locale for the | |
140 specified format. | |
141 | |
142 >>> get_datetime_format(locale='en_US') | |
143 u'{1} {0}' | |
144 | |
145 :param format: the format to use, one of "full", "long", "medium", or | |
146 "short" | |
147 :param locale: the `Locale` object, or a locale string | |
148 :return: the datetime format pattern | |
149 :rtype: `unicode` | |
150 """ | |
151 patterns = Locale.parse(locale).datetime_formats | |
152 if format not in patterns: | |
153 format = None | |
154 return patterns[format] | |
155 | |
1 | 156 def get_time_format(format='medium', locale=LC_TIME): |
157 """Return the time formatting patterns used by the locale for the specified | |
158 format. | |
159 | |
160 >>> get_time_format(locale='en_US') | |
12
a2c54ef107c2
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
8
diff
changeset
|
161 <DateTimePattern u'h:mm:ss a'> |
1 | 162 >>> get_time_format('full', locale='de_DE') |
430 | 163 <DateTimePattern u'HH:mm:ss zzzz'> |
1 | 164 |
165 :param format: the format to use, one of "full", "long", "medium", or | |
166 "short" | |
167 :param locale: the `Locale` object, or a locale string | |
168 :return: the time format pattern | |
33 | 169 :rtype: `DateTimePattern` |
1 | 170 """ |
171 return Locale.parse(locale).time_formats[format] | |
172 | |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
173 def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
174 """Return the timezone associated with the given `datetime` object formatted |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
175 as string indicating the offset from GMT. |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
176 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
177 >>> dt = datetime(2007, 4, 1, 15, 30) |
247
f3fbecf951b0
`get_timezone_gmt()` wasn't getting the locale passed in all cases, which led to test errors when the default locale wasn't configured via environment variables.
cmlenz
parents:
242
diff
changeset
|
178 >>> get_timezone_gmt(dt, locale='en') |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
179 u'GMT+00:00' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
180 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
181 >>> from pytz import timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
182 >>> tz = timezone('America/Los_Angeles') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
183 >>> dt = datetime(2007, 4, 1, 15, 30, tzinfo=tz) |
247
f3fbecf951b0
`get_timezone_gmt()` wasn't getting the locale passed in all cases, which led to test errors when the default locale wasn't configured via environment variables.
cmlenz
parents:
242
diff
changeset
|
184 >>> get_timezone_gmt(dt, locale='en') |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
185 u'GMT-08:00' |
247
f3fbecf951b0
`get_timezone_gmt()` wasn't getting the locale passed in all cases, which led to test errors when the default locale wasn't configured via environment variables.
cmlenz
parents:
242
diff
changeset
|
186 >>> get_timezone_gmt(dt, 'short', locale='en') |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
187 u'-0800' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
188 |
375
369300a7ebd3
Implement support for aliases in the CLDR data. Closes #68. Also, update to CLDR 1.6, and a much improved `dump_data` script.
cmlenz
parents:
348
diff
changeset
|
189 The long format depends on the locale, for example in France the acronym |
369300a7ebd3
Implement support for aliases in the CLDR data. Closes #68. Also, update to CLDR 1.6, and a much improved `dump_data` script.
cmlenz
parents:
348
diff
changeset
|
190 UTC string is used instead of GMT: |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
191 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
192 >>> get_timezone_gmt(dt, 'long', locale='fr_FR') |
375
369300a7ebd3
Implement support for aliases in the CLDR data. Closes #68. Also, update to CLDR 1.6, and a much improved `dump_data` script.
cmlenz
parents:
348
diff
changeset
|
193 u'UTC-08:00' |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
194 |
247
f3fbecf951b0
`get_timezone_gmt()` wasn't getting the locale passed in all cases, which led to test errors when the default locale wasn't configured via environment variables.
cmlenz
parents:
242
diff
changeset
|
195 :param datetime: the ``datetime`` object; if `None`, the current date and |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
196 time in UTC is used |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
197 :param width: either "long" or "short" |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
198 :param locale: the `Locale` object, or a locale string |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
199 :return: the GMT offset representation of the timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
200 :rtype: `unicode` |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
201 :since: version 0.9 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
202 """ |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
203 if datetime is None: |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
204 datetime = datetime_.utcnow() |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
205 elif isinstance(datetime, (int, long)): |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
206 datetime = datetime_.utcfromtimestamp(datetime).time() |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
207 if datetime.tzinfo is None: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
208 datetime = datetime.replace(tzinfo=UTC) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
209 locale = Locale.parse(locale) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
210 |
455
3f3c1696ad39
Workaround for a weird bug with newer versions of pytz, which fails when `utcoffset()` gets passed a `None` argument. Which it shouldn't be getting in the first place.
cmlenz
parents:
451
diff
changeset
|
211 offset = datetime.tzinfo.utcoffset(datetime) |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
212 seconds = offset.days * 24 * 60 * 60 + offset.seconds |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
213 hours, seconds = divmod(seconds, 3600) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
214 if width == 'short': |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
215 pattern = u'%+03d%02d' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
216 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
217 pattern = locale.zone_formats['gmt'] % '%+03d:%02d' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
218 return pattern % (hours, seconds // 60) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
219 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
220 def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
221 """Return a representation of the given timezone using "location format". |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
222 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
223 The result depends on both the local display name of the country and the |
516 | 224 city associated with the time zone: |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
225 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
226 >>> from pytz import timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
227 >>> tz = timezone('America/St_Johns') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
228 >>> get_timezone_location(tz, locale='de_DE') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
229 u"Kanada (St. John's)" |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
230 >>> tz = timezone('America/Mexico_City') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
231 >>> get_timezone_location(tz, locale='de_DE') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
232 u'Mexiko (Mexiko-Stadt)' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
233 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
234 If the timezone is associated with a country that uses only a single |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
235 timezone, just the localized country name is returned: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
236 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
237 >>> tz = timezone('Europe/Berlin') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
238 >>> get_timezone_name(tz, locale='de_DE') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
239 u'Deutschland' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
240 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
241 :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
242 the timezone; if `None`, the current date and time in |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
243 UTC is assumed |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
244 :param locale: the `Locale` object, or a locale string |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
245 :return: the localized timezone name using location format |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
246 :rtype: `unicode` |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
247 :since: version 0.9 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
248 """ |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
249 if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
250 dt = None |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
251 tzinfo = UTC |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
252 elif isinstance(dt_or_tzinfo, (datetime, time)): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
253 dt = dt_or_tzinfo |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
254 if dt.tzinfo is not None: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
255 tzinfo = dt.tzinfo |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
256 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
257 tzinfo = UTC |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
258 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
259 dt = None |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
260 tzinfo = dt_or_tzinfo |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
261 locale = Locale.parse(locale) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
262 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
263 if hasattr(tzinfo, 'zone'): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
264 zone = tzinfo.zone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
265 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
266 zone = tzinfo.tzname(dt or datetime.utcnow()) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
267 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
268 # Get the canonical time-zone code |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
269 zone = get_global('zone_aliases').get(zone, zone) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
270 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
271 info = locale.time_zones.get(zone, {}) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
272 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
273 # Otherwise, if there is only one timezone for the country, return the |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
274 # localized country name |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
275 region_format = locale.zone_formats['region'] |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
276 territory = get_global('zone_territories').get(zone) |
254
04936a6812af
Fail more gracefully when formatting the timezone for an unknown/invalid territory.
cmlenz
parents:
253
diff
changeset
|
277 if territory not in locale.territories: |
04936a6812af
Fail more gracefully when formatting the timezone for an unknown/invalid territory.
cmlenz
parents:
253
diff
changeset
|
278 territory = 'ZZ' # invalid/unknown |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
279 territory_name = locale.territories[territory] |
254
04936a6812af
Fail more gracefully when formatting the timezone for an unknown/invalid territory.
cmlenz
parents:
253
diff
changeset
|
280 if territory and len(get_global('territory_zones').get(territory, [])) == 1: |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
281 return region_format % (territory_name) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
282 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
283 # Otherwise, include the city in the output |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
284 fallback_format = locale.zone_formats['fallback'] |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
285 if 'city' in info: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
286 city_name = info['city'] |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
287 else: |
345
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
288 metazone = get_global('meta_zones').get(zone) |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
289 metazone_info = locale.meta_zones.get(metazone, {}) |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
290 if 'city' in metazone_info: |
518
9d6fa3d28473
Change occurence of 'metainfo' to 'metazone_info'. 'metainfo' was not
jruigrok
parents:
516
diff
changeset
|
291 city_name = metazone_info['city'] |
345
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
292 elif '/' in zone: |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
293 city_name = zone.split('/', 1)[1].replace('_', ' ') |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
294 else: |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
295 city_name = zone.replace('_', ' ') |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
296 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
297 return region_format % (fallback_format % { |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
298 '0': city_name, |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
299 '1': territory_name |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
300 }) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
301 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
302 def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False, |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
303 locale=LC_TIME): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
304 r"""Return the localized display name for the given timezone. The timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
305 may be specified using a ``datetime`` or `tzinfo` object. |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
306 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
307 >>> from pytz import timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
308 >>> dt = time(15, 30, tzinfo=timezone('America/Los_Angeles')) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
309 >>> get_timezone_name(dt, locale='en_US') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
310 u'Pacific Standard Time' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
311 >>> get_timezone_name(dt, width='short', locale='en_US') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
312 u'PST' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
313 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
314 If this function gets passed only a `tzinfo` object and no concrete |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
315 `datetime`, the returned display name is indenpendent of daylight savings |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
316 time. This can be used for example for selecting timezones, or to set the |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
317 time of events that recur across DST changes: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
318 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
319 >>> tz = timezone('America/Los_Angeles') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
320 >>> get_timezone_name(tz, locale='en_US') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
321 u'Pacific Time' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
322 >>> get_timezone_name(tz, 'short', locale='en_US') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
323 u'PT' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
324 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
325 If no localized display name for the timezone is available, and the timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
326 is associated with a country that uses only a single timezone, the name of |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
327 that country is returned, formatted according to the locale: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
328 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
329 >>> tz = timezone('Europe/Berlin') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
330 >>> get_timezone_name(tz, locale='de_DE') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
331 u'Deutschland' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
332 >>> get_timezone_name(tz, locale='pt_BR') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
333 u'Hor\xe1rio Alemanha' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
334 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
335 On the other hand, if the country uses multiple timezones, the city is also |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
336 included in the representation: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
337 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
338 >>> tz = timezone('America/St_Johns') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
339 >>> get_timezone_name(tz, locale='de_DE') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
340 u"Kanada (St. John's)" |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
341 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
342 The `uncommon` parameter can be set to `True` to enable the use of timezone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
343 representations that are not commonly used by the requested locale. For |
451 | 344 example, while in French the central European timezone is usually |
323 | 345 abbreviated as "HEC", in Canadian French, this abbreviation is not in |
346 common use, so a generic name would be chosen by default: | |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
347 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
348 >>> tz = timezone('Europe/Paris') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
349 >>> get_timezone_name(tz, 'short', locale='fr_CA') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
350 u'France' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
351 >>> get_timezone_name(tz, 'short', uncommon=True, locale='fr_CA') |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
352 u'HEC' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
353 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
354 :param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
355 the timezone; if a ``tzinfo`` object is used, the |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
356 resulting display name will be generic, i.e. |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
357 independent of daylight savings time; if `None`, the |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
358 current date in UTC is assumed |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
359 :param width: either "long" or "short" |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
360 :param uncommon: whether even uncommon timezone abbreviations should be used |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
361 :param locale: the `Locale` object, or a locale string |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
362 :return: the timezone display name |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
363 :rtype: `unicode` |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
364 :since: version 0.9 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
365 :see: `LDML Appendix J: Time Zone Display Names |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
366 <http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_ |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
367 """ |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
368 if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
369 dt = None |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
370 tzinfo = UTC |
256 | 371 elif isinstance(dt_or_tzinfo, (datetime, time)): |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
372 dt = dt_or_tzinfo |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
373 if dt.tzinfo is not None: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
374 tzinfo = dt.tzinfo |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
375 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
376 tzinfo = UTC |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
377 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
378 dt = None |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
379 tzinfo = dt_or_tzinfo |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
380 locale = Locale.parse(locale) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
381 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
382 if hasattr(tzinfo, 'zone'): |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
383 zone = tzinfo.zone |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
384 else: |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
385 zone = tzinfo.tzname(dt) |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
386 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
387 # Get the canonical time-zone code |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
388 zone = get_global('zone_aliases').get(zone, zone) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
389 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
390 info = locale.time_zones.get(zone, {}) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
391 # Try explicitly translated zone names first |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
392 if width in info: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
393 if dt is None: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
394 field = 'generic' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
395 else: |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
396 dst = tzinfo.dst(dt) |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
397 if dst is None: |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
398 field = 'generic' |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
399 elif dst == 0: |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
400 field = 'standard' |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
401 else: |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
402 field = 'daylight' |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
403 if field in info[width]: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
404 return info[width][field] |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
405 |
345
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
406 metazone = get_global('meta_zones').get(zone) |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
407 if metazone: |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
408 metazone_info = locale.meta_zones.get(metazone, {}) |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
409 if width in metazone_info and (uncommon or metazone_info.get('common')): |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
410 if dt is None: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
411 field = 'generic' |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
412 else: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
413 field = tzinfo.dst(dt) and 'daylight' or 'standard' |
345
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
414 if field in metazone_info[width]: |
64d340f76701
Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents:
344
diff
changeset
|
415 return metazone_info[width][field] |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
416 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
417 # If we have a concrete datetime, we assume that the result can't be |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
418 # independent of daylight savings time, so we return the GMT offset |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
419 if dt is not None: |
253
ba30864779cc
Fix for `get_timezone_name` when falling back to GMT display.
cmlenz
parents:
247
diff
changeset
|
420 return get_timezone_gmt(dt, width=width, locale=locale) |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
421 |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
422 return get_timezone_location(dt_or_tzinfo, locale=locale) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
423 |
33 | 424 def format_date(date=None, format='medium', locale=LC_TIME): |
101
1312ad6b624d
Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents:
72
diff
changeset
|
425 """Return a date formatted according to the given pattern. |
1 | 426 |
427 >>> d = date(2007, 04, 01) | |
428 >>> format_date(d, locale='en_US') | |
429 u'Apr 1, 2007' | |
430 >>> format_date(d, format='full', locale='de_DE') | |
431 u'Sonntag, 1. April 2007' | |
432 | |
16 | 433 If you don't want to use the locale default formats, you can specify a |
434 custom date pattern: | |
435 | |
29 | 436 >>> format_date(d, "EEE, MMM d, ''yy", locale='en') |
16 | 437 u"Sun, Apr 1, '07" |
438 | |
33 | 439 :param date: the ``date`` or ``datetime`` object; if `None`, the current |
440 date is used | |
16 | 441 :param format: one of "full", "long", "medium", or "short", or a custom |
442 date/time pattern | |
19
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
443 :param locale: a `Locale` object or a locale identifier |
1 | 444 :rtype: `unicode` |
19
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
445 |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
446 :note: If the pattern contains time fields, an `AttributeError` will be |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
447 raised when trying to apply the formatting. This is also true if |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
448 the value of ``date`` parameter is actually a ``datetime`` object, |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
449 as this function automatically converts that to a ``date``. |
1 | 450 """ |
33 | 451 if date is None: |
452 date = date_.today() | |
453 elif isinstance(date, datetime): | |
18
77a68f88f6bc
Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents:
16
diff
changeset
|
454 date = date.date() |
34 | 455 |
1 | 456 locale = Locale.parse(locale) |
457 if format in ('full', 'long', 'medium', 'short'): | |
458 format = get_date_format(format, locale=locale) | |
459 pattern = parse_pattern(format) | |
502
0985a4562967
Small speed improvement for format_date() by getting rid of duplicate parse_pattern.
jruigrok
parents:
455
diff
changeset
|
460 return pattern.apply(date, locale) |
1 | 461 |
34 | 462 def format_datetime(datetime=None, format='medium', tzinfo=None, |
463 locale=LC_TIME): | |
433
2ce20477c392
Mark up two docstrings as raw (r""") in order to get the escaped characters
jruigrok
parents:
430
diff
changeset
|
464 r"""Return a date formatted according to the given pattern. |
1 | 465 |
33 | 466 >>> dt = datetime(2007, 04, 01, 15, 30) |
467 >>> format_datetime(dt, locale='en_US') | |
468 u'Apr 1, 2007 3:30:00 PM' | |
469 | |
34 | 470 For any pattern requiring the display of the time-zone, the third-party |
471 ``pytz`` package is needed to explicitly specify the time-zone: | |
472 | |
473 >>> from pytz import timezone | |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
474 >>> format_datetime(dt, 'full', tzinfo=timezone('Europe/Paris'), |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
475 ... locale='fr_FR') |
433
2ce20477c392
Mark up two docstrings as raw (r""") in order to get the escaped characters
jruigrok
parents:
430
diff
changeset
|
476 u'dimanche 1 avril 2007 17:30:00 Heure avanc\xe9e de l\u2019Europe centrale' |
34 | 477 >>> format_datetime(dt, "yyyy.MM.dd G 'at' HH:mm:ss zzz", |
478 ... tzinfo=timezone('US/Eastern'), locale='en') | |
479 u'2007.04.01 AD at 11:30:00 EDT' | |
480 | |
33 | 481 :param datetime: the `datetime` object; if `None`, the current date and |
482 time is used | |
16 | 483 :param format: one of "full", "long", "medium", or "short", or a custom |
484 date/time pattern | |
29 | 485 :param tzinfo: the timezone to apply to the time for display |
19
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
486 :param locale: a `Locale` object or a locale identifier |
1 | 487 :rtype: `unicode` |
488 """ | |
33 | 489 if datetime is None: |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
490 datetime = datetime_.utcnow() |
34 | 491 elif isinstance(datetime, (int, long)): |
376
a7980c2e77a6
Fix conversion of timestamp to `datetime` in `format_datetime()`
cmlenz
parents:
375
diff
changeset
|
492 datetime = datetime_.utcfromtimestamp(datetime) |
34 | 493 elif isinstance(datetime, time): |
494 datetime = datetime_.combine(date.today(), datetime) | |
495 if datetime.tzinfo is None: | |
496 datetime = datetime.replace(tzinfo=UTC) | |
497 if tzinfo is not None: | |
498 datetime = datetime.astimezone(tzinfo) | |
101
1312ad6b624d
Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents:
72
diff
changeset
|
499 if hasattr(tzinfo, 'normalize'): # pytz |
34 | 500 datetime = tzinfo.normalize(datetime) |
501 | |
18
77a68f88f6bc
Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents:
16
diff
changeset
|
502 locale = Locale.parse(locale) |
77a68f88f6bc
Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents:
16
diff
changeset
|
503 if format in ('full', 'long', 'medium', 'short'): |
33 | 504 return get_datetime_format(format, locale=locale) \ |
34 | 505 .replace('{0}', format_time(datetime, format, tzinfo=None, |
33 | 506 locale=locale)) \ |
507 .replace('{1}', format_date(datetime, format, locale=locale)) | |
508 else: | |
509 return parse_pattern(format).apply(datetime, locale) | |
1 | 510 |
34 | 511 def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME): |
433
2ce20477c392
Mark up two docstrings as raw (r""") in order to get the escaped characters
jruigrok
parents:
430
diff
changeset
|
512 r"""Return a time formatted according to the given pattern. |
1 | 513 |
514 >>> t = time(15, 30) | |
515 >>> format_time(t, locale='en_US') | |
516 u'3:30:00 PM' | |
517 >>> format_time(t, format='short', locale='de_DE') | |
518 u'15:30' | |
519 | |
16 | 520 If you don't want to use the locale default formats, you can specify a |
521 custom time pattern: | |
522 | |
523 >>> format_time(t, "hh 'o''clock' a", locale='en') | |
524 u"03 o'clock PM" | |
525 | |
29 | 526 For any pattern requiring the display of the time-zone, the third-party |
527 ``pytz`` package is needed to explicitly specify the time-zone: | |
528 | |
101
1312ad6b624d
Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents:
72
diff
changeset
|
529 >>> from pytz import timezone |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
530 >>> t = datetime(2007, 4, 1, 15, 30) |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
531 >>> tzinfo = timezone('Europe/Paris') |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
532 >>> t = tzinfo.localize(t) |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
533 >>> format_time(t, format='full', tzinfo=tzinfo, locale='fr_FR') |
433
2ce20477c392
Mark up two docstrings as raw (r""") in order to get the escaped characters
jruigrok
parents:
430
diff
changeset
|
534 u'15:30:00 Heure avanc\xe9e de l\u2019Europe centrale' |
34 | 535 >>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=timezone('US/Eastern'), |
536 ... locale='en') | |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
537 u"09 o'clock AM, Eastern Daylight Time" |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
538 |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
539 As that example shows, when this function gets passed a |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
540 ``datetime.datetime`` value, the actual time in the formatted string is |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
541 adjusted to the timezone specified by the `tzinfo` parameter. If the |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
542 ``datetime`` is "naive" (i.e. it has no associated timezone information), |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
543 it is assumed to be in UTC. |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
544 |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
545 These timezone calculations are **not** performed if the value is of type |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
546 ``datetime.time``, as without date information there's no way to determine |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
547 what a given time would translate to in a different timezone without |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
548 information about whether daylight savings time is in effect or not. This |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
549 means that time values are left as-is, and the value of the `tzinfo` |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
550 parameter is only used to display the timezone name if needed: |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
551 |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
552 >>> t = time(15, 30) |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
553 >>> format_time(t, format='full', tzinfo=timezone('Europe/Paris'), |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
554 ... locale='fr_FR') |
430 | 555 u'15:30:00 Heure normale de l\u2019Europe centrale' |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
556 >>> format_time(t, format='full', tzinfo=timezone('US/Eastern'), |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
557 ... locale='en_US') |
430 | 558 u'3:30:00 PM Eastern Standard Time' |
29 | 559 |
33 | 560 :param time: the ``time`` or ``datetime`` object; if `None`, the current |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
561 time in UTC is used |
16 | 562 :param format: one of "full", "long", "medium", or "short", or a custom |
563 date/time pattern | |
29 | 564 :param tzinfo: the time-zone to apply to the time for display |
19
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
565 :param locale: a `Locale` object or a locale identifier |
1 | 566 :rtype: `unicode` |
19
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
567 |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
568 :note: If the pattern contains date fields, an `AttributeError` will be |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
569 raised when trying to apply the formatting. This is also true if |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
570 the value of ``time`` parameter is actually a ``datetime`` object, |
c0c92d11f1ab
Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents:
18
diff
changeset
|
571 as this function automatically converts that to a ``time``. |
1 | 572 """ |
33 | 573 if time is None: |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
574 time = datetime.utcnow() |
33 | 575 elif isinstance(time, (int, long)): |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
576 time = datetime.utcfromtimestamp(time) |
29 | 577 if time.tzinfo is None: |
34 | 578 time = time.replace(tzinfo=UTC) |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
579 if isinstance(time, datetime): |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
580 if tzinfo is not None: |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
581 time = time.astimezone(tzinfo) |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
582 if hasattr(tzinfo, 'normalize'): # pytz |
348
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
583 time = tzinfo.normalize(time) |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
584 time = time.timetz() |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
585 elif tzinfo is not None: |
6482dc682455
Fixes for timezone calculations in time formatting (#83).
cmlenz
parents:
345
diff
changeset
|
586 time = time.replace(tzinfo=tzinfo) |
34 | 587 |
1 | 588 locale = Locale.parse(locale) |
589 if format in ('full', 'long', 'medium', 'short'): | |
590 format = get_time_format(format, locale=locale) | |
591 return parse_pattern(format).apply(time, locale) | |
592 | |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
593 TIMEDELTA_UNITS = ( |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
594 ('year', 3600 * 24 * 365), |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
595 ('month', 3600 * 24 * 30), |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
596 ('week', 3600 * 24 * 7), |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
597 ('day', 3600 * 24), |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
598 ('hour', 3600), |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
599 ('minute', 60), |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
600 ('second', 1) |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
601 ) |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
602 |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
603 def format_timedelta(delta, granularity='second', threshold=.85, locale=LC_TIME): |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
604 """Return a time delta according to the rules of the given locale. |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
605 |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
606 >>> format_timedelta(timedelta(weeks=12), locale='en_US') |
430 | 607 u'3 mths' |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
608 >>> format_timedelta(timedelta(seconds=1), locale='es') |
430 | 609 u'1 s' |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
610 |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
611 The granularity parameter can be provided to alter the lowest unit |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
612 presented, which defaults to a second. |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
613 |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
614 >>> format_timedelta(timedelta(hours=3), granularity='day', |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
615 ... locale='en_US') |
395
b4d207b1522d
The `format_timedelta` function now returns, for example, ?1 day? instead of ?0 days? if the granularity is `day` and the delta is less than a day but greater than zero.
cmlenz
parents:
394
diff
changeset
|
616 u'1 day' |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
617 |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
618 The threshold parameter can be used to determine at which value the |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
619 presentation switches to the next higher unit. A higher threshold factor |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
620 means the presentation will switch later. For example: |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
621 |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
622 >>> format_timedelta(timedelta(hours=23), threshold=0.9, locale='en_US') |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
623 u'1 day' |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
624 >>> format_timedelta(timedelta(hours=23), threshold=1.1, locale='en_US') |
430 | 625 u'23 hrs' |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
626 |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
627 :param delta: a ``timedelta`` object representing the time difference to |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
628 format, or the delta in seconds as an `int` value |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
629 :param granularity: determines the smallest unit that should be displayed, |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
630 the value can be one of "year", "month", "week", "day", |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
631 "hour", "minute" or "second" |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
632 :param threshold: factor that determines at which point the presentation |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
633 switches to the next higher unit |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
634 :param locale: a `Locale` object or a locale identifier |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
635 :rtype: `unicode` |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
636 """ |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
637 if isinstance(delta, timedelta): |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
638 seconds = int((delta.days * 86400) + delta.seconds) |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
639 else: |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
640 seconds = delta |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
641 locale = Locale.parse(locale) |
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
642 |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
643 for unit, secs_per_unit in TIMEDELTA_UNITS: |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
644 value = abs(seconds) / secs_per_unit |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
645 if value >= threshold or unit == granularity: |
395
b4d207b1522d
The `format_timedelta` function now returns, for example, ?1 day? instead of ?0 days? if the granularity is `day` and the delta is less than a day but greater than zero.
cmlenz
parents:
394
diff
changeset
|
646 if unit == granularity and value > 0: |
b4d207b1522d
The `format_timedelta` function now returns, for example, ?1 day? instead of ?0 days? if the granularity is `day` and the delta is less than a day but greater than zero.
cmlenz
parents:
394
diff
changeset
|
647 value = max(1, value) |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
648 value = int(round(value)) |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
649 plural_form = locale.plural_form(value) |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
650 pattern = locale._data['unit_patterns'][unit][plural_form] |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
651 return pattern.replace('{0}', str(value)) |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
652 |
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
653 return u'' |
390
ecf110e7f604
Preliminary support for timedelta formatting (see #126), and import/expose the locale plural rules from the CLDR.
cmlenz
parents:
376
diff
changeset
|
654 |
1 | 655 def parse_date(string, locale=LC_TIME): |
38
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
656 """Parse a date from a string. |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
657 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
658 This function uses the date format for the locale as a hint to determine |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
659 the order in which the date fields appear in the string. |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
660 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
661 >>> parse_date('4/1/04', locale='en_US') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
662 datetime.date(2004, 4, 1) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
663 >>> parse_date('01.04.2004', locale='de_DE') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
664 datetime.date(2004, 4, 1) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
665 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
666 :param string: the string containing the date |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
667 :param locale: a `Locale` object or a locale identifier |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
668 :return: the parsed date |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
669 :rtype: `date` |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
670 """ |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
671 # TODO: try ISO format first? |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
672 format = get_date_format(locale=locale).pattern.lower() |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
673 year_idx = format.index('y') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
674 month_idx = format.index('m') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
675 if month_idx < 0: |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
676 month_idx = format.index('l') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
677 day_idx = format.index('d') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
678 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
679 indexes = [(year_idx, 'Y'), (month_idx, 'M'), (day_idx, 'D')] |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
680 indexes.sort() |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
681 indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
682 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
683 # FIXME: this currently only supports numbers, but should also support month |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
684 # names, both in the requested locale, and english |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
685 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
686 numbers = re.findall('(\d+)', string) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
687 year = numbers[indexes['Y']] |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
688 if len(year) == 2: |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
689 year = 2000 + int(year) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
690 else: |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
691 year = int(year) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
692 month = int(numbers[indexes['M']]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
693 day = int(numbers[indexes['D']]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
694 if month > 12: |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
695 month, day = day, month |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
696 return date(year, month, day) |
1 | 697 |
698 def parse_datetime(string, locale=LC_TIME): | |
46 | 699 """Parse a date and time from a string. |
700 | |
701 This function uses the date and time formats for the locale as a hint to | |
702 determine the order in which the time fields appear in the string. | |
703 | |
704 :param string: the string containing the date and time | |
705 :param locale: a `Locale` object or a locale identifier | |
706 :return: the parsed date/time | |
707 :rtype: `datetime` | |
708 """ | |
1 | 709 raise NotImplementedError |
710 | |
711 def parse_time(string, locale=LC_TIME): | |
46 | 712 """Parse a time from a string. |
38
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
713 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
714 This function uses the time format for the locale as a hint to determine |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
715 the order in which the time fields appear in the string. |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
716 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
717 >>> parse_time('15:30:00', locale='en_US') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
718 datetime.time(15, 30) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
719 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
720 :param string: the string containing the time |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
721 :param locale: a `Locale` object or a locale identifier |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
722 :return: the parsed time |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
723 :rtype: `time` |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
724 """ |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
725 # TODO: try ISO format first? |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
726 format = get_time_format(locale=locale).pattern.lower() |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
727 hour_idx = format.index('h') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
728 if hour_idx < 0: |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
729 hour_idx = format.index('k') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
730 min_idx = format.index('m') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
731 sec_idx = format.index('s') |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
732 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
733 indexes = [(hour_idx, 'H'), (min_idx, 'M'), (sec_idx, 'S')] |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
734 indexes.sort() |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
735 indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
736 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
737 # FIXME: support 12 hour clock, and 0-based hour specification |
46 | 738 # and seconds should be optional, maybe minutes too |
739 # oh, and time-zones, of course | |
38
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
740 |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
741 numbers = re.findall('(\d+)', string) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
742 hour = int(numbers[indexes['H']]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
743 minute = int(numbers[indexes['M']]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
744 second = int(numbers[indexes['S']]) |
a22b7656e9ae
Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents:
34
diff
changeset
|
745 return time(hour, minute, second) |
1 | 746 |
747 | |
12
a2c54ef107c2
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
8
diff
changeset
|
748 class DateTimePattern(object): |
1 | 749 |
750 def __init__(self, pattern, format): | |
751 self.pattern = pattern | |
752 self.format = format | |
753 | |
754 def __repr__(self): | |
755 return '<%s %r>' % (type(self).__name__, self.pattern) | |
756 | |
757 def __unicode__(self): | |
758 return self.pattern | |
759 | |
760 def __mod__(self, other): | |
391
3eb859adc5de
Fixed a bug in plural.py that caused a traceback for some locales, changed the `__mod__` DateTimePattern to not raise exceptions but return NotImplemented.
aronacher
parents:
390
diff
changeset
|
761 if type(other) is not DateTimeFormat: |
3eb859adc5de
Fixed a bug in plural.py that caused a traceback for some locales, changed the `__mod__` DateTimePattern to not raise exceptions but return NotImplemented.
aronacher
parents:
390
diff
changeset
|
762 return NotImplemented |
1 | 763 return self.format % other |
764 | |
765 def apply(self, datetime, locale): | |
766 return self % DateTimeFormat(datetime, locale) | |
767 | |
768 | |
769 class DateTimeFormat(object): | |
770 | |
771 def __init__(self, value, locale): | |
772 assert isinstance(value, (date, datetime, time)) | |
29 | 773 if isinstance(value, (datetime, time)) and value.tzinfo is None: |
774 value = value.replace(tzinfo=UTC) | |
1 | 775 self.value = value |
776 self.locale = Locale.parse(locale) | |
777 | |
778 def __getitem__(self, name): | |
15 | 779 char = name[0] |
780 num = len(name) | |
781 if char == 'G': | |
782 return self.format_era(char, num) | |
215
d37628e752c4
Dummy/stub implementation for week-in-year and week-in-month date format fields. Also, treat extended year the same as the regular year field, not even ICU seems to handle it specially.
cmlenz
parents:
129
diff
changeset
|
783 elif char in ('y', 'Y', 'u'): |
15 | 784 return self.format_year(char, num) |
785 elif char in ('Q', 'q'): | |
786 return self.format_quarter(char, num) | |
787 elif char in ('M', 'L'): | |
788 return self.format_month(char, num) | |
215
d37628e752c4
Dummy/stub implementation for week-in-year and week-in-month date format fields. Also, treat extended year the same as the regular year field, not even ICU seems to handle it specially.
cmlenz
parents:
129
diff
changeset
|
789 elif char in ('w', 'W'): |
d37628e752c4
Dummy/stub implementation for week-in-year and week-in-month date format fields. Also, treat extended year the same as the regular year field, not even ICU seems to handle it specially.
cmlenz
parents:
129
diff
changeset
|
790 return self.format_week(char, num) |
15 | 791 elif char == 'd': |
792 return self.format(self.value.day, num) | |
221
898b9450f274
Implement day-of-year date format field. Closes #49.
cmlenz
parents:
217
diff
changeset
|
793 elif char == 'D': |
898b9450f274
Implement day-of-year date format field. Closes #49.
cmlenz
parents:
217
diff
changeset
|
794 return self.format_day_of_year(num) |
241
9fedbb6f9871
Implement day-of-week-in-month field in date formatting. Closes #50.
cmlenz
parents:
240
diff
changeset
|
795 elif char == 'F': |
9fedbb6f9871
Implement day-of-week-in-month field in date formatting. Closes #50.
cmlenz
parents:
240
diff
changeset
|
796 return self.format_day_of_week_in_month() |
15 | 797 elif char in ('E', 'e', 'c'): |
798 return self.format_weekday(char, num) | |
799 elif char == 'a': | |
800 return self.format_period(char) | |
801 elif char == 'h': | |
273 | 802 if self.value.hour % 12 == 0: |
803 return self.format(12, num) | |
804 else: | |
805 return self.format(self.value.hour % 12, num) | |
15 | 806 elif char == 'H': |
807 return self.format(self.value.hour, num) | |
18
77a68f88f6bc
Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents:
16
diff
changeset
|
808 elif char == 'K': |
273 | 809 return self.format(self.value.hour % 12, num) |
18
77a68f88f6bc
Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents:
16
diff
changeset
|
810 elif char == 'k': |
273 | 811 if self.value.hour == 0: |
812 return self.format(24, num) | |
813 else: | |
274 | 814 return self.format(self.value.hour, num) |
15 | 815 elif char == 'm': |
816 return self.format(self.value.minute, num) | |
817 elif char == 's': | |
818 return self.format(self.value.second, num) | |
216
1f3c3924b1b5
Support for fractional seconds field in date formatting. Closes #47.
cmlenz
parents:
215
diff
changeset
|
819 elif char == 'S': |
217 | 820 return self.format_frac_seconds(num) |
821 elif char == 'A': | |
822 return self.format_milliseconds_in_day(num) | |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
823 elif char in ('z', 'Z', 'v', 'V'): |
29 | 824 return self.format_timezone(char, num) |
1 | 825 else: |
15 | 826 raise KeyError('Unsupported date/time field %r' % char) |
1 | 827 |
15 | 828 def format_era(self, char, num): |
1 | 829 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)] |
830 era = int(self.value.year >= 0) | |
831 return get_era_names(width, self.locale)[era] | |
832 | |
15 | 833 def format_year(self, char, num): |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
834 value = self.value.year |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
835 if char.isupper(): |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
836 week = self.get_week_number(self.get_day_of_year()) |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
837 if week == 0: |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
838 value -= 1 |
1 | 839 year = self.format(value, num) |
840 if num == 2: | |
841 year = year[-2:] | |
842 return year | |
843 | |
396 | 844 def format_quarter(self, char, num): |
845 quarter = (self.value.month - 1) // 3 + 1 | |
846 if num <= 2: | |
847 return ('%%0%dd' % num) % quarter | |
848 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num] | |
849 context = {'Q': 'format', 'q': 'stand-alone'}[char] | |
850 return get_quarter_names(width, context, self.locale)[quarter] | |
851 | |
15 | 852 def format_month(self, char, num): |
1 | 853 if num <= 2: |
854 return ('%%0%dd' % num) % self.value.month | |
855 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num] | |
344
4cba69c7d4bf
Fix for incorrect month context lookup in date formatting. Closes #75. Thanks to Andrew Stromnov for reporting the problem and providing a patch.
cmlenz
parents:
325
diff
changeset
|
856 context = {'M': 'format', 'L': 'stand-alone'}[char] |
1 | 857 return get_month_names(width, context, self.locale)[self.value.month] |
858 | |
215
d37628e752c4
Dummy/stub implementation for week-in-year and week-in-month date format fields. Also, treat extended year the same as the regular year field, not even ICU seems to handle it specially.
cmlenz
parents:
129
diff
changeset
|
859 def format_week(self, char, num): |
239 | 860 if char.islower(): # week of year |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
861 day_of_year = self.get_day_of_year() |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
862 week = self.get_week_number(day_of_year) |
240 | 863 if week == 0: |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
864 date = self.value - timedelta(days=day_of_year) |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
865 week = self.get_week_number(self.get_day_of_year(date), |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
866 date.weekday()) |
240 | 867 return self.format(week, num) |
239 | 868 else: # week of month |
240 | 869 week = self.get_week_number(self.value.day) |
870 if week == 0: | |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
871 date = self.value - timedelta(days=self.value.day) |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
872 week = self.get_week_number(date.day, date.weekday()) |
240 | 873 pass |
874 return '%d' % week | |
215
d37628e752c4
Dummy/stub implementation for week-in-year and week-in-month date format fields. Also, treat extended year the same as the regular year field, not even ICU seems to handle it specially.
cmlenz
parents:
129
diff
changeset
|
875 |
15 | 876 def format_weekday(self, char, num): |
877 if num < 3: | |
878 if char.islower(): | |
879 value = 7 - self.locale.first_week_day + self.value.weekday() | |
880 return self.format(value % 7 + 1, num) | |
881 num = 3 | |
882 weekday = self.value.weekday() | |
883 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num] | |
884 context = {3: 'format', 4: 'format', 5: 'stand-alone'}[num] | |
1 | 885 return get_day_names(width, context, self.locale)[weekday] |
886 | |
221
898b9450f274
Implement day-of-year date format field. Closes #49.
cmlenz
parents:
217
diff
changeset
|
887 def format_day_of_year(self, num): |
239 | 888 return self.format(self.get_day_of_year(), num) |
221
898b9450f274
Implement day-of-year date format field. Closes #49.
cmlenz
parents:
217
diff
changeset
|
889 |
241
9fedbb6f9871
Implement day-of-week-in-month field in date formatting. Closes #50.
cmlenz
parents:
240
diff
changeset
|
890 def format_day_of_week_in_month(self): |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
891 return '%d' % ((self.value.day - 1) // 7 + 1) |
241
9fedbb6f9871
Implement day-of-week-in-month field in date formatting. Closes #50.
cmlenz
parents:
240
diff
changeset
|
892 |
15 | 893 def format_period(self, char): |
273 | 894 period = {0: 'am', 1: 'pm'}[int(self.value.hour >= 12)] |
1 | 895 return get_period_names(locale=self.locale)[period] |
896 | |
217 | 897 def format_frac_seconds(self, num): |
216
1f3c3924b1b5
Support for fractional seconds field in date formatting. Closes #47.
cmlenz
parents:
215
diff
changeset
|
898 value = str(self.value.microsecond) |
1f3c3924b1b5
Support for fractional seconds field in date formatting. Closes #47.
cmlenz
parents:
215
diff
changeset
|
899 return self.format(round(float('.%s' % value), num) * 10**num, num) |
1f3c3924b1b5
Support for fractional seconds field in date formatting. Closes #47.
cmlenz
parents:
215
diff
changeset
|
900 |
217 | 901 def format_milliseconds_in_day(self, num): |
902 msecs = self.value.microsecond // 1000 + self.value.second * 1000 + \ | |
903 self.value.minute * 60000 + self.value.hour * 3600000 | |
904 return self.format(msecs, num) | |
905 | |
29 | 906 def format_timezone(self, char, num): |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
907 width = {3: 'short', 4: 'long'}[max(3, num)] |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
908 if char == 'z': |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
909 return get_timezone_name(self.value, width, locale=self.locale) |
29 | 910 elif char == 'Z': |
247
f3fbecf951b0
`get_timezone_gmt()` wasn't getting the locale passed in all cases, which led to test errors when the default locale wasn't configured via environment variables.
cmlenz
parents:
242
diff
changeset
|
911 return get_timezone_gmt(self.value, width, locale=self.locale) |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
912 elif char == 'v': |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
913 return get_timezone_name(self.value.tzinfo, width, |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
914 locale=self.locale) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
915 elif char == 'V': |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
916 if num == 1: |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
917 return get_timezone_name(self.value.tzinfo, width, |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
918 uncommon=True, locale=self.locale) |
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
919 return get_timezone_location(self.value.tzinfo, locale=self.locale) |
29 | 920 |
1 | 921 def format(self, value, length): |
922 return ('%%0%dd' % length) % value | |
923 | |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
924 def get_day_of_year(self, date=None): |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
925 if date is None: |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
926 date = self.value |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
927 return (date - date_(date.year, 1, 1)).days + 1 |
239 | 928 |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
929 def get_week_number(self, day_of_period, day_of_week=None): |
239 | 930 """Return the number of the week of a day within a period. This may be |
931 the week number in a year or the week number in a month. | |
932 | |
933 Usually this will return a value equal to or greater than 1, but if the | |
934 first week of the period is so short that it actually counts as the last | |
935 week of the previous period, this function will return 0. | |
936 | |
937 >>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('de_DE')) | |
938 >>> format.get_week_number(6) | |
939 1 | |
940 | |
941 >>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('en_US')) | |
942 >>> format.get_week_number(6) | |
943 2 | |
944 | |
945 :param day_of_period: the number of the day in the period (usually | |
946 either the day of month or the day of year) | |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
947 :param day_of_week: the week day; if ommitted, the week day of the |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
948 current date is assumed |
239 | 949 """ |
242
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
950 if day_of_week is None: |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
951 day_of_week = self.value.weekday() |
059b74719f6b
Finish implementation of day-of-year and day-of-month for now, and fix implementation of year-of-week-of-year field. Closes #46. I suspect there are still cases not entirely covered by this implementation, but those can be filed as separate tickets.
cmlenz
parents:
241
diff
changeset
|
952 first_day = (day_of_week - self.locale.first_week_day - |
239 | 953 day_of_period + 1) % 7 |
954 if first_day < 0: | |
955 first_day += 7 | |
394
0f7f4226f765
Doc improvements for the new `format_timedelta` function.
cmlenz
parents:
391
diff
changeset
|
956 week_number = (day_of_period + first_day - 1) // 7 |
239 | 957 if 7 - first_day >= self.locale.min_week_days: |
958 week_number += 1 | |
959 return week_number | |
960 | |
1 | 961 |
962 PATTERN_CHARS = { | |
15 | 963 'G': [1, 2, 3, 4, 5], # era |
964 'y': None, 'Y': None, 'u': None, # year | |
965 'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter | |
966 'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month | |
967 'w': [1, 2], 'W': [1], # week | |
968 'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day | |
969 'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day | |
970 'a': [1], # period | |
971 'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour | |
972 'm': [1, 2], # minute | |
973 's': [1, 2], 'S': None, 'A': None, # second | |
233
bc22f5aef216
Upgraded to CLDR 1.5 and improved timezone formatting.
cmlenz
parents:
221
diff
changeset
|
974 'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4], 'v': [1, 4], 'V': [1, 4] # zone |
1 | 975 } |
976 | |
977 def parse_pattern(pattern): | |
978 """Parse date, time, and datetime format patterns. | |
979 | |
980 >>> parse_pattern("MMMMd").format | |
981 u'%(MMMM)s%(d)s' | |
982 >>> parse_pattern("MMM d, yyyy").format | |
983 u'%(MMM)s %(d)s, %(yyyy)s' | |
16 | 984 |
985 Pattern can contain literal strings in single quotes: | |
986 | |
1 | 987 >>> parse_pattern("H:mm' Uhr 'z").format |
988 u'%(H)s:%(mm)s Uhr %(z)s' | |
989 | |
16 | 990 An actual single quote can be used by using two adjacent single quote |
991 characters: | |
992 | |
993 >>> parse_pattern("hh' o''clock'").format | |
994 u"%(hh)s o'clock" | |
995 | |
1 | 996 :param pattern: the formatting pattern to parse |
997 """ | |
12
a2c54ef107c2
* Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents:
8
diff
changeset
|
998 if type(pattern) is DateTimePattern: |
1 | 999 return pattern |
1000 | |
1001 result = [] | |
1002 quotebuf = None | |
1003 charbuf = [] | |
1004 fieldchar = [''] | |
1005 fieldnum = [0] | |
1006 | |
1007 def append_chars(): | |
1008 result.append(''.join(charbuf).replace('%', '%%')) | |
1009 del charbuf[:] | |
1010 | |
1011 def append_field(): | |
1012 limit = PATTERN_CHARS[fieldchar[0]] | |
15 | 1013 if limit and fieldnum[0] not in limit: |
1 | 1014 raise ValueError('Invalid length for field: %r' |
1015 % (fieldchar[0] * fieldnum[0])) | |
1016 result.append('%%(%s)s' % (fieldchar[0] * fieldnum[0])) | |
1017 fieldchar[0] = '' | |
1018 fieldnum[0] = 0 | |
1019 | |
16 | 1020 for idx, char in enumerate(pattern.replace("''", '\0')): |
1 | 1021 if quotebuf is None: |
1022 if char == "'": # quote started | |
1023 if fieldchar[0]: | |
1024 append_field() | |
1025 elif charbuf: | |
1026 append_chars() | |
1027 quotebuf = [] | |
1028 elif char in PATTERN_CHARS: | |
1029 if charbuf: | |
1030 append_chars() | |
1031 if char == fieldchar[0]: | |
1032 fieldnum[0] += 1 | |
1033 else: | |
1034 if fieldchar[0]: | |
1035 append_field() | |
1036 fieldchar[0] = char | |
1037 fieldnum[0] = 1 | |
1038 else: | |
1039 if fieldchar[0]: | |
1040 append_field() | |
1041 charbuf.append(char) | |
1042 | |
1043 elif quotebuf is not None: | |
16 | 1044 if char == "'": # end of quote |
1 | 1045 charbuf.extend(quotebuf) |
1046 quotebuf = None | |
1047 else: # inside quote | |
1048 quotebuf.append(char) | |
1049 | |
1050 if fieldchar[0]: | |
1051 append_field() | |
1052 elif charbuf: | |
1053 append_chars() | |
1054 | |
16 | 1055 return DateTimePattern(pattern, u''.join(result).replace('\0', "'")) |