38
36
datetime_ = datetime
40
def get_timezone(zone=None):
41
"""Looks up a timezone by name and returns it. The timezone object
42
returned comes from ``pytz`` and corresponds to the `tzinfo` interface and
43
can be used with all of the functions of Babel that operate with dates.
45
If a timezone is not known a :exc:`LookupError` is raised. If `zone`
46
is ``None`` a local zone object is returned.
48
:param zone: the name of the timezone to look up. If a timezone object
49
itself is passed in, mit's returned unchanged.
53
if not isinstance(zone, string_types):
56
return _pytz.timezone(zone)
57
except _pytz.UnknownTimeZoneError:
58
raise LookupError('Unknown timezone %s' % zone)
61
def get_next_timezone_transition(zone=None, dt=None):
62
"""Given a timezone it will return a :class:`TimezoneTransition` object
63
that holds the information about the next timezone transition that's going
64
to happen. For instance this can be used to detect when the next DST
65
change is going to happen and how it looks like.
67
The transition is calculated relative to the given datetime object. The
68
next transition that follows the date is used. If a transition cannot
69
be found the return value will be `None`.
71
Transition information can only be provided for timezones returned by
72
the :func:`get_timezone` function.
74
:param zone: the timezone for which the transition should be looked up.
75
If not provided the local timezone is used.
76
:param dt: the date after which the next transition should be found.
77
If not given the current time is assumed.
79
zone = get_timezone(zone)
81
dt = datetime.utcnow()
83
dt = dt.replace(tzinfo=None)
85
if not hasattr(zone, '_utc_transition_times'):
86
raise TypeError('Given timezone does not have UTC transition '
87
'times. This can happen because the operating '
88
'system fallback local timezone is used or a '
89
'custom timezone object')
92
idx = max(0, bisect_right(zone._utc_transition_times, dt))
93
old_trans = zone._transition_info[idx - 1]
94
new_trans = zone._transition_info[idx]
95
old_tz = zone._tzinfos[old_trans]
96
new_tz = zone._tzinfos[new_trans]
97
except (LookupError, ValueError):
100
return TimezoneTransition(
101
activates=zone._utc_transition_times[idx],
108
class TimezoneTransition(object):
109
"""A helper object that represents the return value from
110
:func:`get_next_timezone_transition`.
113
def __init__(self, activates, from_tzinfo, to_tzinfo, reference_date=None):
114
#: the time of the activation of the timezone transition in UTC.
115
self.activates = activates
116
#: the timezone from where the transition starts.
117
self.from_tzinfo = from_tzinfo
118
#: the timezone for after the transition.
119
self.to_tzinfo = to_tzinfo
120
#: the reference date that was provided. This is the `dt` parameter
121
#: to the :func:`get_next_timezone_transition`.
122
self.reference_date = reference_date
126
"""The name of the timezone before the transition."""
127
return self.from_tzinfo._tzname
131
"""The name of the timezone after the transition."""
132
return self.to_tzinfo._tzname
135
def from_offset(self):
136
"""The UTC offset in seconds before the transition."""
137
return int(self.from_tzinfo._utcoffset.total_seconds())
141
"""The UTC offset in seconds after the transition."""
142
return int(self.to_tzinfo._utcoffset.total_seconds())
145
return '<TimezoneTransition %s -> %s (%s)>' % (
41
152
def get_period_names(locale=LC_TIME):
42
153
"""Return the names for day periods (AM/PM) used by the locale.
44
155
>>> get_period_names(locale='en_US')['am']
47
158
:param locale: the `Locale` object, or a locale string
48
:return: the dictionary of period names
51
160
return Locale.parse(locale).periods
53
163
def get_day_names(width='wide', context='format', locale=LC_TIME):
54
164
"""Return the day names used by the locale for the specified format.
56
166
>>> get_day_names('wide', locale='en_US')[1]
58
168
>>> get_day_names('abbreviated', locale='es')[1]
60
170
>>> get_day_names('narrow', context='stand-alone', locale='de_DE')[1]
63
173
:param width: the width to use, one of "wide", "abbreviated", or "narrow"
64
174
:param context: the context, either "format" or "stand-alone"
65
175
:param locale: the `Locale` object, or a locale string
66
:return: the dictionary of day names
69
177
return Locale.parse(locale).days[context][width]
71
180
def get_month_names(width='wide', context='format', locale=LC_TIME):
72
181
"""Return the month names used by the locale for the specified format.
74
183
>>> get_month_names('wide', locale='en_US')[1]
76
185
>>> get_month_names('abbreviated', locale='es')[1]
78
187
>>> get_month_names('narrow', context='stand-alone', locale='de_DE')[1]
81
190
:param width: the width to use, one of "wide", "abbreviated", or "narrow"
82
191
:param context: the context, either "format" or "stand-alone"
83
192
:param locale: the `Locale` object, or a locale string
84
:return: the dictionary of month names
87
194
return Locale.parse(locale).months[context][width]
89
197
def get_quarter_names(width='wide', context='format', locale=LC_TIME):
90
198
"""Return the quarter names used by the locale for the specified format.
92
200
>>> get_quarter_names('wide', locale='en_US')[1]
94
202
>>> get_quarter_names('abbreviated', locale='de_DE')[1]
97
205
:param width: the width to use, one of "wide", "abbreviated", or "narrow"
98
206
:param context: the context, either "format" or "stand-alone"
99
207
:param locale: the `Locale` object, or a locale string
100
:return: the dictionary of quarter names
103
209
return Locale.parse(locale).quarters[context][width]
105
212
def get_era_names(width='wide', locale=LC_TIME):
106
213
"""Return the era names used by the locale for the specified format.
108
215
>>> get_era_names('wide', locale='en_US')[1]
110
217
>>> get_era_names('abbreviated', locale='de_DE')[1]
113
220
:param width: the width to use, either "wide", "abbreviated", or "narrow"
114
221
:param locale: the `Locale` object, or a locale string
115
:return: the dictionary of era names
118
223
return Locale.parse(locale).eras[width]
120
226
def get_date_format(format='medium', locale=LC_TIME):
121
227
"""Return the date formatting patterns used by the locale for the specified
124
230
>>> get_date_format(locale='en_US')
125
<DateTimePattern u'MMM d, yyyy'>
231
<DateTimePattern u'MMM d, y'>
126
232
>>> get_date_format('full', locale='de_DE')
127
<DateTimePattern u'EEEE, d. MMMM yyyy'>
233
<DateTimePattern u'EEEE, d. MMMM y'>
129
235
:param format: the format to use, one of "full", "long", "medium", or
131
237
:param locale: the `Locale` object, or a locale string
132
:return: the date format pattern
133
:rtype: `DateTimePattern`
135
239
return Locale.parse(locale).date_formats[format]
137
242
def get_datetime_format(format='medium', locale=LC_TIME):
138
243
"""Return the datetime formatting patterns used by the locale for the
139
244
specified format.
141
246
>>> get_datetime_format(locale='en_US')
144
249
:param format: the format to use, one of "full", "long", "medium", or
146
251
:param locale: the `Locale` object, or a locale string
147
:return: the datetime format pattern
150
253
patterns = Locale.parse(locale).datetime_formats
151
254
if format not in patterns:
153
256
return patterns[format]
155
259
def get_time_format(format='medium', locale=LC_TIME):
156
260
"""Return the time formatting patterns used by the locale for the specified
159
263
>>> get_time_format(locale='en_US')
160
264
<DateTimePattern u'h:mm:ss a'>
161
265
>>> get_time_format('full', locale='de_DE')
162
<DateTimePattern u'HH:mm:ss v'>
266
<DateTimePattern u'HH:mm:ss zzzz'>
164
268
:param format: the format to use, one of "full", "long", "medium", or
166
270
:param locale: the `Locale` object, or a locale string
167
:return: the time format pattern
168
:rtype: `DateTimePattern`
170
272
return Locale.parse(locale).time_formats[format]
172
275
def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME):
173
276
"""Return the timezone associated with the given `datetime` object formatted
174
277
as string indicating the offset from GMT.
176
279
>>> dt = datetime(2007, 4, 1, 15, 30)
177
280
>>> get_timezone_gmt(dt, locale='en')
180
>>> from pytz import timezone
181
>>> tz = timezone('America/Los_Angeles')
283
>>> tz = get_timezone('America/Los_Angeles')
182
284
>>> dt = datetime(2007, 4, 1, 15, 30, tzinfo=tz)
183
285
>>> get_timezone_gmt(dt, locale='en')
185
287
>>> get_timezone_gmt(dt, 'short', locale='en')
188
290
The long format depends on the locale, for example in France the acronym
189
291
UTC string is used instead of GMT:
191
293
>>> get_timezone_gmt(dt, 'long', locale='fr_FR')
296
.. versionadded:: 0.9
194
298
:param datetime: the ``datetime`` object; if `None`, the current date and
195
299
time in UTC is used
196
300
:param width: either "long" or "short"
197
301
:param locale: the `Locale` object, or a locale string
198
:return: the GMT offset representation of the timezone
202
303
if datetime is None:
203
304
datetime = datetime_.utcnow()
204
elif isinstance(datetime, (int, long)):
305
elif isinstance(datetime, integer_types):
205
306
datetime = datetime_.utcfromtimestamp(datetime).time()
206
307
if datetime.tzinfo is None:
207
308
datetime = datetime.replace(tzinfo=UTC)
216
317
pattern = locale.zone_formats['gmt'] % '%+03d:%02d'
217
318
return pattern % (hours, seconds // 60)
219
321
def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
220
322
"""Return a representation of the given timezone using "location format".
222
324
The result depends on both the local display name of the country and the
223
325
city associated with the time zone:
225
>>> from pytz import timezone
226
>>> tz = timezone('America/St_Johns')
227
>>> get_timezone_location(tz, locale='de_DE')
228
u"Kanada (St. John's)"
229
>>> tz = timezone('America/Mexico_City')
230
>>> get_timezone_location(tz, locale='de_DE')
231
u'Mexiko (Mexiko-Stadt)'
327
>>> tz = get_timezone('America/St_Johns')
328
>>> get_timezone_location(tz, locale='de_DE')
329
u"Kanada (St. John's) Zeit"
330
>>> tz = get_timezone('America/Mexico_City')
331
>>> get_timezone_location(tz, locale='de_DE')
332
u'Mexiko (Mexiko-Stadt) Zeit'
233
334
If the timezone is associated with a country that uses only a single
234
335
timezone, just the localized country name is returned:
236
>>> tz = timezone('Europe/Berlin')
337
>>> tz = get_timezone('Europe/Berlin')
237
338
>>> get_timezone_name(tz, locale='de_DE')
339
u'Mitteleurop\\xe4ische Zeit'
341
.. versionadded:: 0.9
240
343
:param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
241
344
the timezone; if `None`, the current date and time in
243
346
:param locale: the `Locale` object, or a locale string
244
347
:return: the localized timezone name using location format
248
if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
349
if dt_or_tzinfo is None:
352
elif isinstance(dt_or_tzinfo, string_types):
354
tzinfo = get_timezone(dt_or_tzinfo)
355
elif isinstance(dt_or_tzinfo, integer_types):
251
358
elif isinstance(dt_or_tzinfo, (datetime, time)):
298
405
'1': territory_name
301
409
def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False,
410
locale=LC_TIME, zone_variant=None):
303
411
r"""Return the localized display name for the given timezone. The timezone
304
412
may be specified using a ``datetime`` or `tzinfo` object.
306
>>> from pytz import timezone
307
>>> dt = time(15, 30, tzinfo=timezone('America/Los_Angeles'))
414
>>> dt = time(15, 30, tzinfo=get_timezone('America/Los_Angeles'))
308
415
>>> get_timezone_name(dt, locale='en_US')
309
416
u'Pacific Standard Time'
310
417
>>> get_timezone_name(dt, width='short', locale='en_US')
313
420
If this function gets passed only a `tzinfo` object and no concrete
314
421
`datetime`, the returned display name is indenpendent of daylight savings
315
422
time. This can be used for example for selecting timezones, or to set the
316
423
time of events that recur across DST changes:
318
>>> tz = timezone('America/Los_Angeles')
425
>>> tz = get_timezone('America/Los_Angeles')
319
426
>>> get_timezone_name(tz, locale='en_US')
321
428
>>> get_timezone_name(tz, 'short', locale='en_US')
324
431
If no localized display name for the timezone is available, and the timezone
325
432
is associated with a country that uses only a single timezone, the name of
326
433
that country is returned, formatted according to the locale:
328
>>> tz = timezone('Europe/Berlin')
435
>>> tz = get_timezone('Europe/Berlin')
329
436
>>> get_timezone_name(tz, locale='de_DE')
437
u'Mitteleurop\xe4ische Zeit'
331
438
>>> get_timezone_name(tz, locale='pt_BR')
332
u'Hor\xe1rio Alemanha'
439
u'Hor\xe1rio da Europa Central'
334
441
On the other hand, if the country uses multiple timezones, the city is also
335
442
included in the representation:
337
>>> tz = timezone('America/St_Johns')
444
>>> tz = get_timezone('America/St_Johns')
338
445
>>> get_timezone_name(tz, locale='de_DE')
339
u"Kanada (St. John's)"
341
The `uncommon` parameter can be set to `True` to enable the use of timezone
342
representations that are not commonly used by the requested locale. For
343
example, while in French the central European timezone is usually
344
abbreviated as "HEC", in Canadian French, this abbreviation is not in
345
common use, so a generic name would be chosen by default:
347
>>> tz = timezone('Europe/Paris')
348
>>> get_timezone_name(tz, 'short', locale='fr_CA')
350
>>> get_timezone_name(tz, 'short', uncommon=True, locale='fr_CA')
448
Note that short format is currently not supported for all timezones and
449
all locales. This is partially because not every timezone has a short
450
code in every locale. In that case it currently falls back to the long
453
For more information see `LDML Appendix J: Time Zone Display Names
454
<http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_
456
.. versionadded:: 0.9
458
.. versionchanged:: 1.0
459
Added `zone_variant` support.
353
461
:param dt_or_tzinfo: the ``datetime`` or ``tzinfo`` object that determines
354
462
the timezone; if a ``tzinfo`` object is used, the
355
463
resulting display name will be generic, i.e.
356
464
independent of daylight savings time; if `None`, the
357
465
current date in UTC is assumed
358
466
:param width: either "long" or "short"
359
:param uncommon: whether even uncommon timezone abbreviations should be used
467
:param uncommon: deprecated and ignored
468
:param zone_variant: defines the zone variation to return. By default the
469
variation is defined from the datetime object
470
passed in. If no datetime object is passed in, the
471
``'generic'`` variation is assumed. The following
472
values are valid: ``'generic'``, ``'daylight'`` and
360
474
:param locale: the `Locale` object, or a locale string
361
:return: the timezone display name
364
:see: `LDML Appendix J: Time Zone Display Names
365
<http://www.unicode.org/reports/tr35/#Time_Zone_Fallback>`_
367
if dt_or_tzinfo is None or isinstance(dt_or_tzinfo, (int, long)):
476
if dt_or_tzinfo is None:
479
elif isinstance(dt_or_tzinfo, string_types):
481
tzinfo = get_timezone(dt_or_tzinfo)
482
elif isinstance(dt_or_tzinfo, integer_types):
370
485
elif isinstance(dt_or_tzinfo, (datetime, time)):
458
567
pattern = parse_pattern(format)
459
568
return pattern.apply(date, locale)
461
571
def format_datetime(datetime=None, format='medium', tzinfo=None,
463
"""Return a date formatted according to the given pattern.
573
r"""Return a date formatted according to the given pattern.
465
575
>>> dt = datetime(2007, 04, 01, 15, 30)
466
576
>>> format_datetime(dt, locale='en_US')
467
u'Apr 1, 2007 3:30:00 PM'
577
u'Apr 1, 2007, 3:30:00 PM'
469
579
For any pattern requiring the display of the time-zone, the third-party
470
580
``pytz`` package is needed to explicitly specify the time-zone:
472
>>> from pytz import timezone
473
>>> format_datetime(dt, 'full', tzinfo=timezone('Europe/Paris'),
582
>>> format_datetime(dt, 'full', tzinfo=get_timezone('Europe/Paris'),
474
583
... locale='fr_FR')
475
u'dimanche 1 avril 2007 17:30:00 HEC'
584
u'dimanche 1 avril 2007 17:30:00 heure avanc\xe9e d\u2019Europe centrale'
476
585
>>> format_datetime(dt, "yyyy.MM.dd G 'at' HH:mm:ss zzz",
477
... tzinfo=timezone('US/Eastern'), locale='en')
586
... tzinfo=get_timezone('US/Eastern'), locale='en')
478
587
u'2007.04.01 AD at 11:30:00 EDT'
480
589
:param datetime: the `datetime` object; if `None`, the current date and
482
591
:param format: one of "full", "long", "medium", or "short", or a custom
483
592
date/time pattern
484
593
:param tzinfo: the timezone to apply to the time for display
485
594
:param locale: a `Locale` object or a locale identifier
488
596
if datetime is None:
489
597
datetime = datetime_.utcnow()
490
elif isinstance(datetime, (int, long)):
598
elif isinstance(datetime, number_types):
491
599
datetime = datetime_.utcfromtimestamp(datetime)
492
600
elif isinstance(datetime, time):
493
601
datetime = datetime_.combine(date.today(), datetime)
494
602
if datetime.tzinfo is None:
495
603
datetime = datetime.replace(tzinfo=UTC)
496
604
if tzinfo is not None:
497
datetime = datetime.astimezone(tzinfo)
605
datetime = datetime.astimezone(get_timezone(tzinfo))
498
606
if hasattr(tzinfo, 'normalize'): # pytz
499
607
datetime = tzinfo.normalize(datetime)
501
609
locale = Locale.parse(locale)
502
610
if format in ('full', 'long', 'medium', 'short'):
503
611
return get_datetime_format(format, locale=locale) \
504
613
.replace('{0}', format_time(datetime, format, tzinfo=None,
505
614
locale=locale)) \
506
615
.replace('{1}', format_date(datetime, format, locale=locale))
508
617
return parse_pattern(format).apply(datetime, locale)
510
620
def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):
511
"""Return a time formatted according to the given pattern.
621
r"""Return a time formatted according to the given pattern.
513
623
>>> t = time(15, 30)
514
624
>>> format_time(t, locale='en_US')
516
626
>>> format_time(t, format='short', locale='de_DE')
519
629
If you don't want to use the locale default formats, you can specify a
520
630
custom time pattern:
522
632
>>> format_time(t, "hh 'o''clock' a", locale='en')
525
For any pattern requiring the display of the time-zone, the third-party
526
``pytz`` package is needed to explicitly specify the time-zone:
528
>>> from pytz import timezone
635
For any pattern requiring the display of the time-zone a
636
timezone has to be specified explicitly:
529
638
>>> t = datetime(2007, 4, 1, 15, 30)
530
>>> tzinfo = timezone('Europe/Paris')
639
>>> tzinfo = get_timezone('Europe/Paris')
531
640
>>> t = tzinfo.localize(t)
532
641
>>> format_time(t, format='full', tzinfo=tzinfo, locale='fr_FR')
534
>>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=timezone('US/Eastern'),
642
u'15:30:00 heure avanc\xe9e d\u2019Europe centrale'
643
>>> format_time(t, "hh 'o''clock' a, zzzz", tzinfo=get_timezone('US/Eastern'),
536
645
u"09 o'clock AM, Eastern Daylight Time"
538
647
As that example shows, when this function gets passed a
539
648
``datetime.datetime`` value, the actual time in the formatted string is
540
649
adjusted to the timezone specified by the `tzinfo` parameter. If the
541
650
``datetime`` is "naive" (i.e. it has no associated timezone information),
542
651
it is assumed to be in UTC.
544
653
These timezone calculations are **not** performed if the value is of type
545
654
``datetime.time``, as without date information there's no way to determine
546
655
what a given time would translate to in a different timezone without
547
656
information about whether daylight savings time is in effect or not. This
548
657
means that time values are left as-is, and the value of the `tzinfo`
549
658
parameter is only used to display the timezone name if needed:
551
660
>>> t = time(15, 30)
552
>>> format_time(t, format='full', tzinfo=timezone('Europe/Paris'),
661
>>> format_time(t, format='full', tzinfo=get_timezone('Europe/Paris'),
553
662
... locale='fr_FR')
555
>>> format_time(t, format='full', tzinfo=timezone('US/Eastern'),
663
u'15:30:00 heure normale de l\u2019Europe centrale'
664
>>> format_time(t, format='full', tzinfo=get_timezone('US/Eastern'),
556
665
... locale='en_US')
666
u'3:30:00 PM Eastern Standard Time'
559
668
:param time: the ``time`` or ``datetime`` object; if `None`, the current
560
669
time in UTC is used
561
670
:param format: one of "full", "long", "medium", or "short", or a custom
562
671
date/time pattern
563
672
:param tzinfo: the time-zone to apply to the time for display
564
673
:param locale: a `Locale` object or a locale identifier
567
:note: If the pattern contains date fields, an `AttributeError` will be
568
raised when trying to apply the formatting. This is also true if
569
the value of ``time`` parameter is actually a ``datetime`` object,
570
as this function automatically converts that to a ``time``.
573
676
time = datetime.utcnow()
574
elif isinstance(time, (int, long)):
677
elif isinstance(time, number_types):
575
678
time = datetime.utcfromtimestamp(time)
576
679
if time.tzinfo is None:
577
680
time = time.replace(tzinfo=UTC)
589
692
format = get_time_format(format, locale=locale)
590
693
return parse_pattern(format).apply(time, locale)
697
('year', 3600 * 24 * 365),
698
('month', 3600 * 24 * 30),
699
('week', 3600 * 24 * 7),
707
def format_timedelta(delta, granularity='second', threshold=.85,
708
add_direction=False, format='medium',
710
"""Return a time delta according to the rules of the given locale.
712
>>> format_timedelta(timedelta(weeks=12), locale='en_US')
714
>>> format_timedelta(timedelta(seconds=1), locale='es')
717
The granularity parameter can be provided to alter the lowest unit
718
presented, which defaults to a second.
720
>>> format_timedelta(timedelta(hours=3), granularity='day',
724
The threshold parameter can be used to determine at which value the
725
presentation switches to the next higher unit. A higher threshold factor
726
means the presentation will switch later. For example:
728
>>> format_timedelta(timedelta(hours=23), threshold=0.9, locale='en_US')
730
>>> format_timedelta(timedelta(hours=23), threshold=1.1, locale='en_US')
733
In addition directional information can be provided that informs
734
the user if the date is in the past or in the future:
736
>>> format_timedelta(timedelta(hours=1), add_direction=True)
738
>>> format_timedelta(timedelta(hours=-1), add_direction=True)
741
:param delta: a ``timedelta`` object representing the time difference to
742
format, or the delta in seconds as an `int` value
743
:param granularity: determines the smallest unit that should be displayed,
744
the value can be one of "year", "month", "week", "day",
745
"hour", "minute" or "second"
746
:param threshold: factor that determines at which point the presentation
747
switches to the next higher unit
748
:param add_direction: if this flag is set to `True` the return value will
749
include directional information. For instance a
750
positive timedelta will include the information about
751
it being in the future, a negative will be information
752
about the value being in the past.
753
:param format: the format (currently only "medium" and "short" are supported)
754
:param locale: a `Locale` object or a locale identifier
756
if format not in ('short', 'medium'):
757
raise TypeError('Format can only be one of "short" or "medium"')
758
if isinstance(delta, timedelta):
759
seconds = int((delta.days * 86400) + delta.seconds)
762
locale = Locale.parse(locale)
764
def _iter_choices(unit):
767
yield unit + '-future'
770
yield unit + ':' + format
773
for unit, secs_per_unit in TIMEDELTA_UNITS:
774
value = abs(seconds) / secs_per_unit
775
if value >= threshold or unit == granularity:
776
if unit == granularity and value > 0:
777
value = max(1, value)
778
value = int(round(value))
779
plural_form = locale.plural_form(value)
781
for choice in _iter_choices(unit):
782
patterns = locale._data['unit_patterns'].get(choice)
783
if patterns is not None:
784
pattern = patterns[plural_form]
786
# This really should not happen
789
return pattern.replace('{0}', str(value))
592
794
def parse_date(string, locale=LC_TIME):
593
795
"""Parse a date from a string.
595
797
This function uses the date format for the locale as a hint to determine
596
798
the order in which the date fields appear in the string.
598
800
>>> parse_date('4/1/04', locale='en_US')
599
801
datetime.date(2004, 4, 1)
600
802
>>> parse_date('01.04.2004', locale='de_DE')
601
803
datetime.date(2004, 4, 1)
603
805
:param string: the string containing the date
604
806
:param locale: a `Locale` object or a locale identifier
605
:return: the parsed date
608
808
# TODO: try ISO format first?
609
809
format = get_date_format(locale=locale).pattern.lower()