annotate babel/dates.py @ 217:15ac328954f5

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.
author cmlenz
date Fri, 13 Jul 2007 22:22:03 +0000
parents 669a9b3a24ad
children 0a30f3974997
rev   line source
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
2 #
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2007 Edgewall Software
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
4 # All rights reserved.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
5 #
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
8 # are also available at http://babel.edgewall.org/wiki/License.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
9 #
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://babel.edgewall.org/log/.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
13
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
14 """Locale dependent formatting and parsing of dates and times.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
15
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
16 The default locale for the functions in this module is determined by the
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
17 following environment variables, in that order:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
18
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
19 * ``LC_TIME``,
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
20 * ``LC_ALL``, and
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
21 * ``LANG``
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
22 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
23
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
24 from datetime import date, datetime, time, timedelta, tzinfo
40
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
25 import re
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
26
74
d9c34d2f3d1d More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents: 48
diff changeset
27 from babel.core import default_locale, Locale
41
359ec55de578 Move function for determining the system default locale to `babel.core`, and make it available as a class method on `Locale`.
cmlenz
parents: 40
diff changeset
28 from babel.util import UTC
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
29
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
30 __all__ = ['format_date', 'format_datetime', 'format_time', 'parse_date',
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
31 'parse_datetime', 'parse_time']
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
32 __docformat__ = 'restructuredtext en'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
33
74
d9c34d2f3d1d More explicit module-level function names in `babel.core`. Added `Locale.negotiate` class method.
cmlenz
parents: 48
diff changeset
34 LC_TIME = default_locale('LC_TIME')
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
35
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
36 # Aliases for use in scopes where the modules are shadowed by local variables
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
37 date_ = date
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
38 datetime_ = datetime
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
39 time_ = time
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
40
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
41 def get_period_names(locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
42 """Return the names for day periods (AM/PM) used by the locale.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
43
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
44 >>> get_period_names(locale='en_US')['am']
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
45 u'AM'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
46
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
47 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
48 :return: the dictionary of period names
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
49 :rtype: `dict`
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
50 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
51 return Locale.parse(locale).periods
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
52
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
53 def get_day_names(width='wide', context='format', locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
54 """Return the day names used by the locale for the specified format.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
55
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
56 >>> get_day_names('wide', locale='en_US')[1]
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
57 u'Tuesday'
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
58 >>> get_day_names('abbreviated', locale='es')[1]
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
59 u'mar'
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
60 >>> get_day_names('narrow', context='stand-alone', locale='de_DE')[1]
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
61 u'D'
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
62
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
63 :param width: the width to use, one of "wide", "abbreviated", or "narrow"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
64 :param context: the context, either "format" or "stand-alone"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
65 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
66 :return: the dictionary of day names
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
67 :rtype: `dict`
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
68 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
69 return Locale.parse(locale).days[context][width]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
70
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
71 def get_month_names(width='wide', context='format', locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
72 """Return the month names used by the locale for the specified format.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
73
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
74 >>> get_month_names('wide', locale='en_US')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
75 u'January'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
76 >>> get_month_names('abbreviated', locale='es')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
77 u'ene'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
78 >>> get_month_names('narrow', context='stand-alone', locale='de_DE')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
79 u'J'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
80
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
81 :param width: the width to use, one of "wide", "abbreviated", or "narrow"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
82 :param context: the context, either "format" or "stand-alone"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
83 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
84 :return: the dictionary of month names
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
85 :rtype: `dict`
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
86 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
87 return Locale.parse(locale).months[context][width]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
88
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
89 def get_quarter_names(width='wide', context='format', locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
90 """Return the quarter names used by the locale for the specified format.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
91
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
92 >>> get_quarter_names('wide', locale='en_US')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
93 u'1st quarter'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
94 >>> get_quarter_names('abbreviated', locale='de_DE')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
95 u'Q1'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
96
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
97 :param width: the width to use, one of "wide", "abbreviated", or "narrow"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
98 :param context: the context, either "format" or "stand-alone"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
99 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
100 :return: the dictionary of quarter names
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
101 :rtype: `dict`
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
102 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
103 return Locale.parse(locale).quarters[context][width]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
104
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
105 def get_era_names(width='wide', locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
106 """Return the era names used by the locale for the specified format.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
107
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
108 >>> get_era_names('wide', locale='en_US')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
109 u'Anno Domini'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
110 >>> get_era_names('abbreviated', locale='de_DE')[1]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
111 u'n. Chr.'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
112
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
113 :param width: the width to use, either "wide" or "abbreviated"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
114 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
115 :return: the dictionary of era names
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
116 :rtype: `dict`
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
117 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
118 return Locale.parse(locale).eras[width]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
119
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
120 def get_date_format(format='medium', locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
121 """Return the date formatting patterns used by the locale for the specified
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
122 format.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
123
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
124 >>> get_date_format(locale='en_US')
14
29ef15a6fd75 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 10
diff changeset
125 <DateTimePattern u'MMM d, yyyy'>
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
126 >>> get_date_format('full', locale='de_DE')
14
29ef15a6fd75 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 10
diff changeset
127 <DateTimePattern u'EEEE, d. MMMM yyyy'>
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
128
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
129 :param format: the format to use, one of "full", "long", "medium", or
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
130 "short"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
131 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
132 :return: the date format pattern
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
133 :rtype: `DateTimePattern`
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
134 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
135 return Locale.parse(locale).date_formats[format]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
136
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
137 def get_datetime_format(format='medium', locale=LC_TIME):
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
138 """Return the datetime formatting patterns used by the locale for the
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
139 specified format.
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
140
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
141 >>> get_datetime_format(locale='en_US')
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
142 u'{1} {0}'
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
143
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
144 :param format: the format to use, one of "full", "long", "medium", or
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
145 "short"
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
146 :param locale: the `Locale` object, or a locale string
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
147 :return: the datetime format pattern
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
148 :rtype: `unicode`
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
149 """
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
150 patterns = Locale.parse(locale).datetime_formats
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
151 if format not in patterns:
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
152 format = None
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
153 return patterns[format]
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
154
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
155 def get_time_format(format='medium', locale=LC_TIME):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
156 """Return the time formatting patterns used by the locale for the specified
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
157 format.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
158
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
159 >>> get_time_format(locale='en_US')
14
29ef15a6fd75 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 10
diff changeset
160 <DateTimePattern u'h:mm:ss a'>
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
161 >>> get_time_format('full', locale='de_DE')
14
29ef15a6fd75 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 10
diff changeset
162 <DateTimePattern u"H:mm' Uhr 'z">
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
163
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
164 :param format: the format to use, one of "full", "long", "medium", or
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
165 "short"
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
166 :param locale: the `Locale` object, or a locale string
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
167 :return: the time format pattern
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
168 :rtype: `DateTimePattern`
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
169 """
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
170 return Locale.parse(locale).time_formats[format]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
171
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
172 def format_date(date=None, format='medium', locale=LC_TIME):
103
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
173 """Return a date formatted according to the given pattern.
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
174
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
175 >>> d = date(2007, 04, 01)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
176 >>> format_date(d, locale='en_US')
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
177 u'Apr 1, 2007'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
178 >>> format_date(d, format='full', locale='de_DE')
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
179 u'Sonntag, 1. April 2007'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
180
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
181 If you don't want to use the locale default formats, you can specify a
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
182 custom date pattern:
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
183
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
184 >>> format_date(d, "EEE, MMM d, ''yy", locale='en')
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
185 u"Sun, Apr 1, '07"
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
186
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
187 :param date: the ``date`` or ``datetime`` object; if `None`, the current
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
188 date is used
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
189 :param format: one of "full", "long", "medium", or "short", or a custom
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
190 date/time pattern
21
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
191 :param locale: a `Locale` object or a locale identifier
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
192 :rtype: `unicode`
21
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
193
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
194 :note: If the pattern contains time fields, an `AttributeError` will be
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
195 raised when trying to apply the formatting. This is also true if
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
196 the value of ``date`` parameter is actually a ``datetime`` object,
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
197 as this function automatically converts that to a ``date``.
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
198 """
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
199 if date is None:
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
200 date = date_.today()
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
201 elif isinstance(date, datetime):
20
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
202 date = date.date()
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
203
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
204 locale = Locale.parse(locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
205 if format in ('full', 'long', 'medium', 'short'):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
206 format = get_date_format(format, locale=locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
207 pattern = parse_pattern(format)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
208 return parse_pattern(format).apply(date, locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
209
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
210 def format_datetime(datetime=None, format='medium', tzinfo=None,
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
211 locale=LC_TIME):
103
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
212 """Return a date formatted according to the given pattern.
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
213
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
214 >>> dt = datetime(2007, 04, 01, 15, 30)
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
215 >>> format_datetime(dt, locale='en_US')
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
216 u'Apr 1, 2007 3:30:00 PM'
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
217
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
218 For any pattern requiring the display of the time-zone, the third-party
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
219 ``pytz`` package is needed to explicitly specify the time-zone:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
220
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
221 >>> from pytz import timezone
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
222 >>> format_datetime(dt, 'full', tzinfo=timezone('Europe/Berlin'),
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
223 ... locale='de_DE')
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
224 u'Sonntag, 1. April 2007 17:30 Uhr MESZ'
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
225 >>> format_datetime(dt, "yyyy.MM.dd G 'at' HH:mm:ss zzz",
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
226 ... tzinfo=timezone('US/Eastern'), locale='en')
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
227 u'2007.04.01 AD at 11:30:00 EDT'
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
228
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
229 :param datetime: the `datetime` object; if `None`, the current date and
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
230 time is used
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
231 :param format: one of "full", "long", "medium", or "short", or a custom
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
232 date/time pattern
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
233 :param tzinfo: the timezone to apply to the time for display
21
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
234 :param locale: a `Locale` object or a locale identifier
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
235 :rtype: `unicode`
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
236 """
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
237 if datetime is None:
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
238 datetime = datetime_.now()
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
239 elif isinstance(datetime, (int, long)):
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
240 datetime = datetime.fromtimestamp(datetime)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
241 elif isinstance(datetime, time):
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
242 datetime = datetime_.combine(date.today(), datetime)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
243 if datetime.tzinfo is None:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
244 datetime = datetime.replace(tzinfo=UTC)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
245 if tzinfo is not None:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
246 datetime = datetime.astimezone(tzinfo)
103
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
247 if hasattr(tzinfo, 'normalize'): # pytz
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
248 datetime = tzinfo.normalize(datetime)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
249
20
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
250 locale = Locale.parse(locale)
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
251 if format in ('full', 'long', 'medium', 'short'):
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
252 return get_datetime_format(format, locale=locale) \
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
253 .replace('{0}', format_time(datetime, format, tzinfo=None,
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
254 locale=locale)) \
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
255 .replace('{1}', format_date(datetime, format, locale=locale))
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
256 else:
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
257 return parse_pattern(format).apply(datetime, locale)
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
258
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
259 def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):
103
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
260 """Return a time formatted according to the given pattern.
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
261
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
262 >>> t = time(15, 30)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
263 >>> format_time(t, locale='en_US')
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
264 u'3:30:00 PM'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
265 >>> format_time(t, format='short', locale='de_DE')
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
266 u'15:30'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
267
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
268 If you don't want to use the locale default formats, you can specify a
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
269 custom time pattern:
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
270
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
271 >>> format_time(t, "hh 'o''clock' a", locale='en')
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
272 u"03 o'clock PM"
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
273
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
274 For any pattern requiring the display of the time-zone, the third-party
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
275 ``pytz`` package is needed to explicitly specify the time-zone:
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
276
103
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
277 >>> from pytz import timezone
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
278 >>> t = time(15, 30)
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
279 >>> format_time(t, format='full', tzinfo=timezone('Europe/Berlin'),
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
280 ... locale='de_DE')
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
281 u'17:30 Uhr MESZ'
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
282 >>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=timezone('US/Eastern'),
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
283 ... locale='en')
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
284 u"11 o'clock AM, Eastern Daylight Time"
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
285
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
286 :param time: the ``time`` or ``datetime`` object; if `None`, the current
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
287 time is used
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
288 :param format: one of "full", "long", "medium", or "short", or a custom
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
289 date/time pattern
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
290 :param tzinfo: the time-zone to apply to the time for display
21
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
291 :param locale: a `Locale` object or a locale identifier
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
292 :rtype: `unicode`
21
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
293
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
294 :note: If the pattern contains date fields, an `AttributeError` will be
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
295 raised when trying to apply the formatting. This is also true if
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
296 the value of ``time`` parameter is actually a ``datetime`` object,
646f3f7e6a9a Moved some datetime tests from doctest to unittest, to avoid breaking docutils/epydoc doctest block detection.
cmlenz
parents: 20
diff changeset
297 as this function automatically converts that to a ``time``.
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
298 """
35
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
299 if time is None:
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
300 time = datetime.now().time()
0505d666fa1f * Import datetime patterns from CLDR.
cmlenz
parents: 31
diff changeset
301 elif isinstance(time, (int, long)):
20
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
302 time = datetime.fromtimestamp(time).time()
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
303 elif isinstance(time, datetime):
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
304 time = time.timetz()
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
305 if time.tzinfo is None:
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
306 time = time.replace(tzinfo=UTC)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
307 if tzinfo is not None:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
308 dt = datetime.combine(date.today(), time).astimezone(tzinfo)
103
1ba215a5774d Add wrapper class bundling the various formatting functions bound to a specific locale and time-zone.
cmlenz
parents: 74
diff changeset
309 if hasattr(tzinfo, 'normalize'): # pytz
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
310 dt = tzinfo.normalize(dt)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
311 time = dt.timetz()
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
312
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
313 locale = Locale.parse(locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
314 if format in ('full', 'long', 'medium', 'short'):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
315 format = get_time_format(format, locale=locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
316 return parse_pattern(format).apply(time, locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
317
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
318 def parse_date(string, locale=LC_TIME):
40
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
319 """Parse a date from a string.
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
320
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
321 This function uses the date format for the locale as a hint to determine
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
322 the order in which the date fields appear in the string.
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
323
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
324 >>> parse_date('4/1/04', locale='en_US')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
325 datetime.date(2004, 4, 1)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
326 >>> parse_date('01.04.2004', locale='de_DE')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
327 datetime.date(2004, 4, 1)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
328
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
329 :param string: the string containing the date
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
330 :param locale: a `Locale` object or a locale identifier
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
331 :return: the parsed date
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
332 :rtype: `date`
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
333 """
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
334 # TODO: try ISO format first?
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
335 format = get_date_format(locale=locale).pattern.lower()
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
336 year_idx = format.index('y')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
337 month_idx = format.index('m')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
338 if month_idx < 0:
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
339 month_idx = format.index('l')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
340 day_idx = format.index('d')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
341
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
342 indexes = [(year_idx, 'Y'), (month_idx, 'M'), (day_idx, 'D')]
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
343 indexes.sort()
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
344 indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
345
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
346 # FIXME: this currently only supports numbers, but should also support month
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
347 # names, both in the requested locale, and english
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
348
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
349 numbers = re.findall('(\d+)', string)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
350 year = numbers[indexes['Y']]
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
351 if len(year) == 2:
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
352 year = 2000 + int(year)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
353 else:
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
354 year = int(year)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
355 month = int(numbers[indexes['M']])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
356 day = int(numbers[indexes['D']])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
357 if month > 12:
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
358 month, day = day, month
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
359 return date(year, month, day)
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
360
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
361 def parse_datetime(string, locale=LC_TIME):
48
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
362 """Parse a date and time from a string.
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
363
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
364 This function uses the date and time formats for the locale as a hint to
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
365 determine the order in which the time fields appear in the string.
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
366
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
367 :param string: the string containing the date and time
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
368 :param locale: a `Locale` object or a locale identifier
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
369 :return: the parsed date/time
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
370 :rtype: `datetime`
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
371 """
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
372 raise NotImplementedError
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
373
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
374 def parse_time(string, locale=LC_TIME):
48
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
375 """Parse a time from a string.
40
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
376
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
377 This function uses the time format for the locale as a hint to determine
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
378 the order in which the time fields appear in the string.
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
379
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
380 >>> parse_time('15:30:00', locale='en_US')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
381 datetime.time(15, 30)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
382
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
383 :param string: the string containing the time
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
384 :param locale: a `Locale` object or a locale identifier
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
385 :return: the parsed time
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
386 :rtype: `time`
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
387 """
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
388 # TODO: try ISO format first?
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
389 format = get_time_format(locale=locale).pattern.lower()
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
390 hour_idx = format.index('h')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
391 if hour_idx < 0:
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
392 hour_idx = format.index('k')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
393 min_idx = format.index('m')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
394 sec_idx = format.index('s')
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
395
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
396 indexes = [(hour_idx, 'H'), (min_idx, 'M'), (sec_idx, 'S')]
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
397 indexes.sort()
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
398 indexes = dict([(item[1], idx) for idx, item in enumerate(indexes)])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
399
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
400 # FIXME: support 12 hour clock, and 0-based hour specification
48
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
401 # and seconds should be optional, maybe minutes too
4da7c8f41674 Minor docstring fixes.
cmlenz
parents: 41
diff changeset
402 # oh, and time-zones, of course
40
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
403
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
404 numbers = re.findall('(\d+)', string)
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
405 hour = int(numbers[indexes['H']])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
406 minute = int(numbers[indexes['M']])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
407 second = int(numbers[indexes['S']])
496a5c3f9d6d Started implementation of datetime parsing, using a very basic approach for now.
cmlenz
parents: 36
diff changeset
408 return time(hour, minute, second)
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
409
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
410
14
29ef15a6fd75 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 10
diff changeset
411 class DateTimePattern(object):
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
412
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
413 def __init__(self, pattern, format):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
414 self.pattern = pattern
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
415 self.format = format
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
416
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
417 def __repr__(self):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
418 return '<%s %r>' % (type(self).__name__, self.pattern)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
419
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
420 def __unicode__(self):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
421 return self.pattern
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
422
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
423 def __mod__(self, other):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
424 assert type(other) is DateTimeFormat
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
425 return self.format % other
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
426
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
427 def apply(self, datetime, locale):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
428 return self % DateTimeFormat(datetime, locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
429
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
430
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
431 class DateTimeFormat(object):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
432
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
433 def __init__(self, value, locale):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
434 assert isinstance(value, (date, datetime, time))
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
435 if isinstance(value, (datetime, time)) and value.tzinfo is None:
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
436 value = value.replace(tzinfo=UTC)
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
437 self.value = value
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
438 self.locale = Locale.parse(locale)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
439
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
440 def __getitem__(self, name):
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
441 char = name[0]
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
442 num = len(name)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
443 if char == 'G':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
444 return self.format_era(char, num)
217
15ac328954f5 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: 131
diff changeset
445 elif char in ('y', 'Y', 'u'):
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
446 return self.format_year(char, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
447 elif char in ('Q', 'q'):
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
448 return self.format_quarter(char, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
449 elif char in ('M', 'L'):
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
450 return self.format_month(char, num)
217
15ac328954f5 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: 131
diff changeset
451 elif char in ('w', 'W'):
15ac328954f5 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: 131
diff changeset
452 return self.format_week(char, num)
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
453 elif char == 'd':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
454 return self.format(self.value.day, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
455 elif char in ('E', 'e', 'c'):
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
456 return self.format_weekday(char, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
457 elif char == 'a':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
458 return self.format_period(char)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
459 elif char == 'h':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
460 return self.format(self.value.hour % 12, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
461 elif char == 'H':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
462 return self.format(self.value.hour, num)
20
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
463 elif char == 'K':
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
464 return self.format(self.value.hour % 12 - 1, num)
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
465 elif char == 'k':
dce4cfd4ba5d Started documentation for date formatting, plus some code tweaks in that area.
cmlenz
parents: 18
diff changeset
466 return self.format(self.value.hour + 1, num)
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
467 elif char == 'm':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
468 return self.format(self.value.minute, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
469 elif char == 's':
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
470 return self.format(self.value.second, num)
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
471 elif char in ('z', 'Z', 'v'):
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
472 return self.format_timezone(char, num)
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
473 else:
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
474 raise KeyError('Unsupported date/time field %r' % char)
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
475
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
476 def format_era(self, char, num):
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
477 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[max(3, num)]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
478 era = int(self.value.year >= 0)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
479 return get_era_names(width, self.locale)[era]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
480
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
481 def format_year(self, char, num):
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
482 if char.islower():
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
483 value = self.value.year
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
484 else:
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
485 value = self.value.isocalendar()[0]
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
486 year = self.format(value, num)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
487 if num == 2:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
488 year = year[-2:]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
489 return year
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
490
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
491 def format_month(self, char, num):
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
492 if num <= 2:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
493 return ('%%0%dd' % num) % self.value.month
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
494 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
495 context = {3: 'format', 4: 'format', 5: 'stand-alone'}[num]
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
496 return get_month_names(width, context, self.locale)[self.value.month]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
497
217
15ac328954f5 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: 131
diff changeset
498 def format_week(self, char, num):
15ac328954f5 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: 131
diff changeset
499 # FIXME: this should really be based on the first_week_day and
15ac328954f5 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: 131
diff changeset
500 # min_week_days locale data
15ac328954f5 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: 131
diff changeset
501 if char.islower():
15ac328954f5 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: 131
diff changeset
502 return self.value.strftime('%W')
15ac328954f5 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: 131
diff changeset
503 else:
15ac328954f5 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: 131
diff changeset
504 return '%d' % ((self.value.day + 6 - self.value.weekday()) / 7 + 1)
15ac328954f5 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: 131
diff changeset
505
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
506 def format_weekday(self, char, num):
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
507 if num < 3:
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
508 if char.islower():
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
509 value = 7 - self.locale.first_week_day + self.value.weekday()
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
510 return self.format(value % 7 + 1, num)
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
511 num = 3
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
512 weekday = self.value.weekday()
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
513 width = {3: 'abbreviated', 4: 'wide', 5: 'narrow'}[num]
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
514 context = {3: 'format', 4: 'format', 5: 'stand-alone'}[num]
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
515 return get_day_names(width, context, self.locale)[weekday]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
516
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
517 def format_period(self, char):
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
518 period = {0: 'am', 1: 'pm'}[int(self.value.hour > 12)]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
519 return get_period_names(locale=self.locale)[period]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
520
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
521 def format_timezone(self, char, num):
131
669a9b3a24ad Implement wall-time time-zone display.
cmlenz
parents: 103
diff changeset
522 if char in ('z', 'v'):
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
523 if hasattr(self.value.tzinfo, 'zone'):
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
524 zone = self.value.tzinfo.zone
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
525 else:
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
526 zone = self.value.tzinfo.tzname(self.value)
131
669a9b3a24ad Implement wall-time time-zone display.
cmlenz
parents: 103
diff changeset
527
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
528 # Get the canonical time-zone code
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
529 zone = self.locale.zone_aliases.get(zone, zone)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
530
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
531 # Try explicitly translated zone names first
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
532 display = self.locale.time_zones.get(zone)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
533 if display:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
534 if 'long' in display:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
535 width = {3: 'short', 4: 'long'}[max(3, num)]
131
669a9b3a24ad Implement wall-time time-zone display.
cmlenz
parents: 103
diff changeset
536 if char == 'v':
669a9b3a24ad Implement wall-time time-zone display.
cmlenz
parents: 103
diff changeset
537 dst = 'generic'
669a9b3a24ad Implement wall-time time-zone display.
cmlenz
parents: 103
diff changeset
538 else:
669a9b3a24ad Implement wall-time time-zone display.
cmlenz
parents: 103
diff changeset
539 dst = self.value.dst() and 'daylight' or 'standard'
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
540 return display[width][dst]
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
541 elif 'city' in display:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
542 return display['city']
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
543
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
544 else:
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
545 return zone.split('/', 1)[1]
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
546
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
547 elif char == 'Z':
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
548 offset = self.value.utcoffset()
36
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
549 seconds = offset.days * 24 * 60 * 60 + offset.seconds
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
550 hours, seconds = divmod(seconds, 3600)
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
551 pattern = {3: '%+03d%02d', 4: 'GMT %+03d:%02d'}[max(3, num)]
2e143f1a0003 Extended time-zone support.
cmlenz
parents: 35
diff changeset
552 return pattern % (hours, seconds // 60)
31
3956bb7ff93b More work on timezones.
cmlenz
parents: 21
diff changeset
553
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
554 def format(self, value, length):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
555 return ('%%0%dd' % length) % value
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
556
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
557
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
558 PATTERN_CHARS = {
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
559 'G': [1, 2, 3, 4, 5], # era
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
560 'y': None, 'Y': None, 'u': None, # year
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
561 'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
562 'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
563 'w': [1, 2], 'W': [1], # week
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
564 'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
565 'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
566 'a': [1], # period
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
567 'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
568 'm': [1, 2], # minute
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
569 's': [1, 2], 'S': None, 'A': None, # second
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
570 'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4], 'v': [1, 4] # zone
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
571 }
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
572
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
573 def parse_pattern(pattern):
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
574 """Parse date, time, and datetime format patterns.
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
575
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
576 >>> parse_pattern("MMMMd").format
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
577 u'%(MMMM)s%(d)s'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
578 >>> parse_pattern("MMM d, yyyy").format
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
579 u'%(MMM)s %(d)s, %(yyyy)s'
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
580
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
581 Pattern can contain literal strings in single quotes:
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
582
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
583 >>> parse_pattern("H:mm' Uhr 'z").format
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
584 u'%(H)s:%(mm)s Uhr %(z)s'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
585
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
586 An actual single quote can be used by using two adjacent single quote
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
587 characters:
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
588
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
589 >>> parse_pattern("hh' o''clock'").format
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
590 u"%(hh)s o'clock"
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
591
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
592 :param pattern: the formatting pattern to parse
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
593 """
14
29ef15a6fd75 * Removed pkg_resources/setuptools requirement from various places.
cmlenz
parents: 10
diff changeset
594 if type(pattern) is DateTimePattern:
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
595 return pattern
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
596
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
597 result = []
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
598 quotebuf = None
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
599 charbuf = []
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
600 fieldchar = ['']
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
601 fieldnum = [0]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
602
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
603 def append_chars():
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
604 result.append(''.join(charbuf).replace('%', '%%'))
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
605 del charbuf[:]
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
606
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
607 def append_field():
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
608 limit = PATTERN_CHARS[fieldchar[0]]
17
aa33ad077d24 Minor date formatting improvements.
cmlenz
parents: 14
diff changeset
609 if limit and fieldnum[0] not in limit:
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
610 raise ValueError('Invalid length for field: %r'
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
611 % (fieldchar[0] * fieldnum[0]))
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
612 result.append('%%(%s)s' % (fieldchar[0] * fieldnum[0]))
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
613 fieldchar[0] = ''
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
614 fieldnum[0] = 0
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
615
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
616 for idx, char in enumerate(pattern.replace("''", '\0')):
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
617 if quotebuf is None:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
618 if char == "'": # quote started
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
619 if fieldchar[0]:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
620 append_field()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
621 elif charbuf:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
622 append_chars()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
623 quotebuf = []
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
624 elif char in PATTERN_CHARS:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
625 if charbuf:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
626 append_chars()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
627 if char == fieldchar[0]:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
628 fieldnum[0] += 1
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
629 else:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
630 if fieldchar[0]:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
631 append_field()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
632 fieldchar[0] = char
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
633 fieldnum[0] = 1
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
634 else:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
635 if fieldchar[0]:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
636 append_field()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
637 charbuf.append(char)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
638
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
639 elif quotebuf is not None:
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
640 if char == "'": # end of quote
3
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
641 charbuf.extend(quotebuf)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
642 quotebuf = None
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
643 else: # inside quote
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
644 quotebuf.append(char)
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
645
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
646 if fieldchar[0]:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
647 append_field()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
648 elif charbuf:
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
649 append_chars()
e9eaddab598e Import of initial code base.
cmlenz
parents:
diff changeset
650
18
9fdadd10504c Handle escape chars in datetime patterns.
cmlenz
parents: 17
diff changeset
651 return DateTimePattern(pattern, u''.join(result).replace('\0', "'"))
Copyright (C) 2012-2017 Edgewall Software