annotate babel/dates.py @ 72:4dcdb1d367ec

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