annotate babel/dates.py @ 516:606af7395ad8

fixed spelling in docstring
author fschwarz
date Sat, 05 Mar 2011 09:55:42 +0000
parents 3413235af4d8
children 9d6fa3d28473
rev   line source
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
2 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2007 Edgewall Software
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
4 # All rights reserved.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
5 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
8 # are also available at http://babel.edgewall.org/wiki/License.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
9 #
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://babel.edgewall.org/log/.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
13
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
14 """Locale dependent formatting and parsing of dates and times.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
15
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
16 The default locale for the functions in this module is determined by the
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
17 following environment variables, in that order:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
18
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
19 * ``LC_TIME``,
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
20 * ``LC_ALL``, and
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
21 * ``LANG``
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
22 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
23
394
0f7f4226f765 Doc improvements for the new `format_timedelta` function.
cmlenz
parents: 391
diff changeset
24 from __future__ import division
515
3413235af4d8 Import of tzinfo is not necessary.
jruigrok
parents: 502
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
33 __docformat__ = 'restructuredtext en'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
36
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
37 # Aliases for use in scopes where the modules are shadowed by local variables
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
38 date_ = date
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
39 datetime_ = datetime
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
40 time_ = time
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
41
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
42 def get_period_names(locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
43 """Return the names for day periods (AM/PM) used by the locale.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
44
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
45 >>> get_period_names(locale='en_US')['am']
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
46 u'AM'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
47
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
48 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
49 :return: the dictionary of period names
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
50 :rtype: `dict`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
51 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
52 return Locale.parse(locale).periods
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
53
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
54 def get_day_names(width='wide', context='format', locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
55 """Return the day names used by the locale for the specified format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
56
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
57 >>> get_day_names('wide', locale='en_US')[1]
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
58 u'Tuesday'
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
59 >>> get_day_names('abbreviated', locale='es')[1]
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
60 u'mar'
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
61 >>> get_day_names('narrow', context='stand-alone', locale='de_DE')[1]
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
62 u'D'
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
63
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
64 :param width: the width to use, one of "wide", "abbreviated", or "narrow"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
65 :param context: the context, either "format" or "stand-alone"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
66 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
67 :return: the dictionary of day names
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
68 :rtype: `dict`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
69 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
70 return Locale.parse(locale).days[context][width]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
71
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
72 def get_month_names(width='wide', context='format', locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
73 """Return the month names used by the locale for the specified format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
74
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
75 >>> get_month_names('wide', locale='en_US')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
76 u'January'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
77 >>> get_month_names('abbreviated', locale='es')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
78 u'ene'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
79 >>> get_month_names('narrow', context='stand-alone', locale='de_DE')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
80 u'J'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
81
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
82 :param width: the width to use, one of "wide", "abbreviated", or "narrow"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
83 :param context: the context, either "format" or "stand-alone"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
84 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
85 :return: the dictionary of month names
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
86 :rtype: `dict`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
87 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
88 return Locale.parse(locale).months[context][width]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
89
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
90 def get_quarter_names(width='wide', context='format', locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
91 """Return the quarter names used by the locale for the specified format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
92
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
93 >>> get_quarter_names('wide', locale='en_US')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
94 u'1st quarter'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
95 >>> get_quarter_names('abbreviated', locale='de_DE')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
96 u'Q1'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
97
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
98 :param width: the width to use, one of "wide", "abbreviated", or "narrow"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
99 :param context: the context, either "format" or "stand-alone"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
100 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
101 :return: the dictionary of quarter names
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
102 :rtype: `dict`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
103 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
104 return Locale.parse(locale).quarters[context][width]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
105
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
106 def get_era_names(width='wide', locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
107 """Return the era names used by the locale for the specified format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
108
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
109 >>> get_era_names('wide', locale='en_US')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
110 u'Anno Domini'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
111 >>> get_era_names('abbreviated', locale='de_DE')[1]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
112 u'n. Chr.'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
115 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
116 :return: the dictionary of era names
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
117 :rtype: `dict`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
118 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
119 return Locale.parse(locale).eras[width]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
120
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
121 def get_date_format(format='medium', locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
122 """Return the date formatting patterns used by the locale for the specified
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
123 format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
124
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
125 >>> get_date_format(locale='en_US')
430
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
126 <DateTimePattern u'MMM d, y'>
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
127 >>> get_date_format('full', locale='de_DE')
430
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
128 <DateTimePattern u'EEEE, d. MMMM y'>
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
129
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
130 :param format: the format to use, one of "full", "long", "medium", or
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
131 "short"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
132 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
133 :return: the date format pattern
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
134 :rtype: `DateTimePattern`
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
135 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
136 return Locale.parse(locale).date_formats[format]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
137
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
138 def get_datetime_format(format='medium', locale=LC_TIME):
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
139 """Return the datetime formatting patterns used by the locale for the
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
140 specified format.
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
141
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
142 >>> get_datetime_format(locale='en_US')
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
143 u'{1} {0}'
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
144
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
145 :param format: the format to use, one of "full", "long", "medium", or
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
146 "short"
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
147 :param locale: the `Locale` object, or a locale string
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
148 :return: the datetime format pattern
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
149 :rtype: `unicode`
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
150 """
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
151 patterns = Locale.parse(locale).datetime_formats
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
152 if format not in patterns:
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
153 format = None
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
154 return patterns[format]
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
155
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
156 def get_time_format(format='medium', locale=LC_TIME):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
157 """Return the time formatting patterns used by the locale for the specified
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
158 format.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
159
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
162 >>> get_time_format('full', locale='de_DE')
430
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
163 <DateTimePattern u'HH:mm:ss zzzz'>
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
164
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
165 :param format: the format to use, one of "full", "long", "medium", or
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
166 "short"
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
167 :param locale: the `Locale` object, or a locale string
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
168 :return: the time format pattern
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
169 :rtype: `DateTimePattern`
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
170 """
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
171 return Locale.parse(locale).time_formats[format]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
606af7395ad8 fixed spelling in docstring
fschwarz
parents: 515
diff changeset
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:
64d340f76701 Update to CLDR 1.5.1, which split out the metazone mappings into a separate supplemental file.
cmlenz
parents: 344
diff changeset
291 city_name = metainfo['city']
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
be5a6b72d20c Fix some more typos.
jruigrok
parents: 450
diff changeset
344 example, while in French the central European timezone is usually
323
6e4d20dbf189 Fix typo.
jruigrok
parents: 274
diff changeset
345 abbreviated as "HEC", in Canadian French, this abbreviation is not in
6e4d20dbf189 Fix typo.
jruigrok
parents: 274
diff changeset
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
25c7ccf96f3b Fix typo in [271] that slipped into the check-in.
cmlenz
parents: 255
diff changeset
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
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
426
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
427 >>> d = date(2007, 04, 01)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
428 >>> format_date(d, locale='en_US')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
429 u'Apr 1, 2007'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
430 >>> format_date(d, format='full', locale='de_DE')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
431 u'Sonntag, 1. April 2007'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
432
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
433 If you don't want to use the locale default formats, you can specify a
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
434 custom date pattern:
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
435
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
436 >>> format_date(d, "EEE, MMM d, ''yy", locale='en')
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
437 u"Sun, Apr 1, '07"
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
438
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
439 :param date: the ``date`` or ``datetime`` object; if `None`, the current
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
440 date is used
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
441 :param format: one of "full", "long", "medium", or "short", or a custom
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
450 """
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
451 if date is None:
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
452 date = date_.today()
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
455
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
456 locale = Locale.parse(locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
457 if format in ('full', 'long', 'medium', 'short'):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
458 format = get_date_format(format, locale=locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
461
34
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
462 def format_datetime(datetime=None, format='medium', tzinfo=None,
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
465
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
466 >>> dt = datetime(2007, 04, 01, 15, 30)
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
467 >>> format_datetime(dt, locale='en_US')
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
468 u'Apr 1, 2007 3:30:00 PM'
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
469
34
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
470 For any pattern requiring the display of the time-zone, the third-party
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
471 ``pytz`` package is needed to explicitly specify the time-zone:
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
472
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
477 >>> format_datetime(dt, "yyyy.MM.dd G 'at' HH:mm:ss zzz",
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
478 ... tzinfo=timezone('US/Eastern'), locale='en')
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
479 u'2007.04.01 AD at 11:30:00 EDT'
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
480
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
481 :param datetime: the `datetime` object; if `None`, the current date and
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
482 time is used
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
483 :param format: one of "full", "long", "medium", or "short", or a custom
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
484 date/time pattern
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
487 :rtype: `unicode`
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
488 """
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
493 elif isinstance(datetime, time):
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
494 datetime = datetime_.combine(date.today(), datetime)
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
495 if datetime.tzinfo is None:
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
496 datetime = datetime.replace(tzinfo=UTC)
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
497 if tzinfo is not None:
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
500 datetime = tzinfo.normalize(datetime)
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
504 return get_datetime_format(format, locale=locale) \
34
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
505 .replace('{0}', format_time(datetime, format, tzinfo=None,
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
506 locale=locale)) \
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
507 .replace('{1}', format_date(datetime, format, locale=locale))
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
508 else:
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
509 return parse_pattern(format).apply(datetime, locale)
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
510
34
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
513
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
514 >>> t = time(15, 30)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
515 >>> format_time(t, locale='en_US')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
516 u'3:30:00 PM'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
517 >>> format_time(t, format='short', locale='de_DE')
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
518 u'15:30'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
519
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
520 If you don't want to use the locale default formats, you can specify a
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
521 custom time pattern:
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
522
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
523 >>> format_time(t, "hh 'o''clock' a", locale='en')
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
524 u"03 o'clock PM"
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
525
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
526 For any pattern requiring the display of the time-zone, the third-party
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
527 ``pytz`` package is needed to explicitly specify the time-zone:
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
535 >>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=timezone('US/Eastern'),
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
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
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
558 u'3:30:00 PM Eastern Standard Time'
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
559
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
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
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
562 :param format: one of "full", "long", "medium", or "short", or a custom
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
563 date/time pattern
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
572 """
33
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
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
0740b6d31799 * Import datetime patterns from CLDR.
cmlenz
parents: 29
diff changeset
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
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
577 if time.tzinfo is None:
34
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
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
3666f3d3df15 Extended time-zone support.
cmlenz
parents: 33
diff changeset
587
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
588 locale = Locale.parse(locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
589 if format in ('full', 'long', 'medium', 'short'):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
590 format = get_time_format(format, locale=locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
591 return parse_pattern(format).apply(time, locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
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
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
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
c92473b51411 First changes to accomodate CLDR 1.7's changes.
jruigrok
parents: 396
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
697
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
698 def parse_datetime(string, locale=LC_TIME):
46
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
699 """Parse a date and time from a string.
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
700
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
701 This function uses the date and time formats for the locale as a hint to
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
702 determine the order in which the time fields appear in the string.
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
703
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
704 :param string: the string containing the date and time
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
705 :param locale: a `Locale` object or a locale identifier
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
706 :return: the parsed date/time
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
707 :rtype: `datetime`
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
708 """
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
709 raise NotImplementedError
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
710
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
711 def parse_time(string, locale=LC_TIME):
46
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
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
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
738 # and seconds should be optional, maybe minutes too
306445fbd3ea Minor docstring fixes.
cmlenz
parents: 39
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
746
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
747
12
a2c54ef107c2 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 8
diff changeset
748 class DateTimePattern(object):
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
749
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
750 def __init__(self, pattern, format):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
751 self.pattern = pattern
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
752 self.format = format
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
753
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
754 def __repr__(self):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
755 return '<%s %r>' % (type(self).__name__, self.pattern)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
756
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
757 def __unicode__(self):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
758 return self.pattern
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
759
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
763 return self.format % other
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
764
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
765 def apply(self, datetime, locale):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
766 return self % DateTimeFormat(datetime, locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
767
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
768
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
769 class DateTimeFormat(object):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
770
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
771 def __init__(self, value, locale):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
772 assert isinstance(value, (date, datetime, time))
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
773 if isinstance(value, (datetime, time)) and value.tzinfo is None:
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
774 value = value.replace(tzinfo=UTC)
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
775 self.value = value
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
776 self.locale = Locale.parse(locale)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
777
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
778 def __getitem__(self, name):
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
779 char = name[0]
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
780 num = len(name)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
781 if char == 'G':
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
784 return self.format_year(char, num)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
785 elif char in ('Q', 'q'):
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
786 return self.format_quarter(char, num)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
787 elif char in ('M', 'L'):
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
791 elif char == 'd':
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
797 elif char in ('E', 'e', 'c'):
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
798 return self.format_weekday(char, num)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
799 elif char == 'a':
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
800 return self.format_period(char)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
801 elif char == 'h':
273
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
802 if self.value.hour % 12 == 0:
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
803 return self.format(12, num)
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
804 else:
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
805 return self.format(self.value.hour % 12, num)
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
806 elif char == 'H':
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
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
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
811 if self.value.hour == 0:
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
812 return self.format(24, num)
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
813 else:
274
7de5fdf3c47b Fixed a bug introduced by [301].
jonas
parents: 273
diff changeset
814 return self.format(self.value.hour, num)
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
815 elif char == 'm':
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
816 return self.format(self.value.minute, num)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
817 elif char == 's':
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
820 return self.format_frac_seconds(num)
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
821 elif char == 'A':
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
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
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
824 return self.format_timezone(char, num)
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
825 else:
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
826 raise KeyError('Unsupported date/time field %r' % char)
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
827
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
828 def format_era(self, char, num):
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
829 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
830 era = int(self.value.year >= 0)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
831 return get_era_names(width, self.locale)[era]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
832
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
839 year = self.format(value, num)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
840 if num == 2:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
841 year = year[-2:]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
842 return year
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
843
396
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
844 def format_quarter(self, char, num):
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
845 quarter = (self.value.month - 1) // 3 + 1
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
846 if num <= 2:
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
847 return ('%%0%dd' % num) % quarter
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
848 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
849 context = {'Q': 'format', 'q': 'stand-alone'}[char]
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
850 return get_quarter_names(width, context, self.locale)[quarter]
b283ae0e098d Fixed quarters in date formatting.
cmlenz
parents: 395
diff changeset
851
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
852 def format_month(self, char, num):
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
853 if num <= 2:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
854 return ('%%0%dd' % num) % self.value.month
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
857 return get_month_names(width, context, self.locale)[self.value.month]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
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
e47245bf65b3 More work on #46 (week-of-year/week-of-month).
cmlenz
parents: 239
diff changeset
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
e47245bf65b3 More work on #46 (week-of-year/week-of-month).
cmlenz
parents: 239
diff changeset
867 return self.format(week, num)
239
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
868 else: # week of month
240
e47245bf65b3 More work on #46 (week-of-year/week-of-month).
cmlenz
parents: 239
diff changeset
869 week = self.get_week_number(self.value.day)
e47245bf65b3 More work on #46 (week-of-year/week-of-month).
cmlenz
parents: 239
diff changeset
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
e47245bf65b3 More work on #46 (week-of-year/week-of-month).
cmlenz
parents: 239
diff changeset
873 pass
e47245bf65b3 More work on #46 (week-of-year/week-of-month).
cmlenz
parents: 239
diff changeset
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
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
876 def format_weekday(self, char, num):
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
877 if num < 3:
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
878 if char.islower():
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
879 value = 7 - self.locale.first_week_day + self.value.weekday()
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
880 return self.format(value % 7 + 1, num)
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
881 num = 3
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
882 weekday = self.value.weekday()
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
883 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
884 context = {3: 'format', 4: 'format', 5: 'stand-alone'}[num]
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
885 return get_day_names(width, context, self.locale)[weekday]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
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
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
893 def format_period(self, char):
273
bf9ea4af81a0 Fixed formatting bug with 12-hour clock patterns.
jonas
parents: 256
diff changeset
894 period = {0: 'am', 1: 'pm'}[int(self.value.hour >= 12)]
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
895 return get_period_names(locale=self.locale)[period]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
896
217
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
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
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
901 def format_milliseconds_in_day(self, num):
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
902 msecs = self.value.microsecond // 1000 + self.value.second * 1000 + \
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
903 self.value.minute * 60000 + self.value.hour * 3600000
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
904 return self.format(msecs, num)
4de6f4604830 Implement milliseconds in day (#48).
cmlenz
parents: 216
diff changeset
905
29
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
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
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
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
da1c9610e751 More work on timezones.
cmlenz
parents: 19
diff changeset
920
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
921 def format(self, value, length):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
922 return ('%%0%dd' % length) % value
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
930 """Return the number of the week of a day within a period. This may be
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
931 the week number in a year or the week number in a month.
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
932
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
933 Usually this will return a value equal to or greater than 1, but if the
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
934 first week of the period is so short that it actually counts as the last
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
935 week of the previous period, this function will return 0.
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
936
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
937 >>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('de_DE'))
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
938 >>> format.get_week_number(6)
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
939 1
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
940
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
941 >>> format = DateTimeFormat(date(2006, 1, 8), Locale.parse('en_US'))
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
942 >>> format.get_week_number(6)
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
943 2
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
944
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
945 :param day_of_period: the number of the day in the period (usually
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
953 day_of_period + 1) % 7
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
954 if first_day < 0:
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
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
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
957 if 7 - first_day >= self.locale.min_week_days:
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
958 week_number += 1
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
959 return week_number
4afe02d81083 Again, properly implement week-in-year (#46).
cmlenz
parents: 238
diff changeset
960
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
961
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
962 PATTERN_CHARS = {
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
963 'G': [1, 2, 3, 4, 5], # era
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
964 'y': None, 'Y': None, 'u': None, # year
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
965 'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
966 'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
967 'w': [1, 2], 'W': [1], # week
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
968 'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
969 'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
970 'a': [1], # period
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
971 'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
972 'm': [1, 2], # minute
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
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
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
975 }
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
976
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
977 def parse_pattern(pattern):
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
978 """Parse date, time, and datetime format patterns.
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
979
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
980 >>> parse_pattern("MMMMd").format
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
981 u'%(MMMM)s%(d)s'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
982 >>> parse_pattern("MMM d, yyyy").format
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
983 u'%(MMM)s %(d)s, %(yyyy)s'
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
984
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
985 Pattern can contain literal strings in single quotes:
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
986
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
987 >>> parse_pattern("H:mm' Uhr 'z").format
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
988 u'%(H)s:%(mm)s Uhr %(z)s'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
989
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
990 An actual single quote can be used by using two adjacent single quote
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
991 characters:
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
992
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
993 >>> parse_pattern("hh' o''clock'").format
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
994 u"%(hh)s o'clock"
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
995
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
996 :param pattern: the formatting pattern to parse
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
997 """
12
a2c54ef107c2 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 8
diff changeset
998 if type(pattern) is DateTimePattern:
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
999 return pattern
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1000
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1001 result = []
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1002 quotebuf = None
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1003 charbuf = []
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1004 fieldchar = ['']
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1005 fieldnum = [0]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1006
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1007 def append_chars():
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1008 result.append(''.join(charbuf).replace('%', '%%'))
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1009 del charbuf[:]
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1010
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1011 def append_field():
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1012 limit = PATTERN_CHARS[fieldchar[0]]
15
76985c08a339 Minor date formatting improvements.
cmlenz
parents: 12
diff changeset
1013 if limit and fieldnum[0] not in limit:
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1014 raise ValueError('Invalid length for field: %r'
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1015 % (fieldchar[0] * fieldnum[0]))
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1016 result.append('%%(%s)s' % (fieldchar[0] * fieldnum[0]))
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1017 fieldchar[0] = ''
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1018 fieldnum[0] = 0
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1019
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
1020 for idx, char in enumerate(pattern.replace("''", '\0')):
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1021 if quotebuf is None:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1022 if char == "'": # quote started
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1023 if fieldchar[0]:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1024 append_field()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1025 elif charbuf:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1026 append_chars()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1027 quotebuf = []
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1028 elif char in PATTERN_CHARS:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1029 if charbuf:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1030 append_chars()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1031 if char == fieldchar[0]:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1032 fieldnum[0] += 1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1033 else:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1034 if fieldchar[0]:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1035 append_field()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1036 fieldchar[0] = char
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1037 fieldnum[0] = 1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1038 else:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1039 if fieldchar[0]:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1040 append_field()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1041 charbuf.append(char)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1042
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1043 elif quotebuf is not None:
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
1044 if char == "'": # end of quote
1
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1045 charbuf.extend(quotebuf)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1046 quotebuf = None
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1047 else: # inside quote
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1048 quotebuf.append(char)
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1049
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1050 if fieldchar[0]:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1051 append_field()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1052 elif charbuf:
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1053 append_chars()
f71ca60f2a4a Import of initial code base.
cmlenz
parents:
diff changeset
1054
16
ed154241c08d Handle escape chars in datetime patterns.
cmlenz
parents: 15
diff changeset
1055 return DateTimePattern(pattern, u''.join(result).replace('\0', "'"))
Copyright (C) 2012-2017 Edgewall Software