Skip to content

Commit 3aa3f29

Browse files
committed
Merge pull request #265 from mbirtwell/add-date-time-skeletons
Add support for date-time skeletons
2 parents 07aa84f + 65e20c1 commit 3aa3f29

File tree

5 files changed

+59
-0
lines changed

5 files changed

+59
-0
lines changed

babel/core.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,19 @@ def datetime_formats(self):
731731
"""
732732
return self._data['datetime_formats']
733733

734+
@property
735+
def datetime_skeletons(self):
736+
"""Locale patterns for formatting parts of a datetime.
737+
738+
>>> Locale('en').datetime_skeletons['MEd']
739+
<DateTimePattern u'E, M/d'>
740+
>>> Locale('fr').datetime_skeletons['MEd']
741+
<DateTimePattern u'E dd/MM'>
742+
>>> Locale('fr').datetime_skeletons['H']
743+
<DateTimePattern u"HH 'h'">
744+
"""
745+
return self._data['datetime_skeletons']
746+
734747
@property
735748
def plural_form(self):
736749
"""Plural rules for the locale.

babel/dates.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,34 @@ def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):
694694
return parse_pattern(format).apply(time, locale)
695695

696696

697+
def format_skeleton(skeleton, datetime=None, tzinfo=None, locale=LC_TIME):
698+
r"""Return a time and/or date formatted according to the given pattern.
699+
700+
The skeletons are defined in the CLDR data and provide more flexibility
701+
than the simple short/long/medium formats, but are a bit harder to use.
702+
The are defined using the date/time symbols without order or punctuation
703+
and map to a suitable format for the given locale.
704+
705+
>>> t = datetime(2007, 4, 1, 15, 30)
706+
>>> format_skeleton('MMMEd', t, locale='fr')
707+
u'dim. 1 avr.'
708+
>>> format_skeleton('MMMEd', t, locale='en')
709+
u'Sun, Apr 1'
710+
711+
After the skeleton is resolved to a pattern `format_datetime` is called so
712+
all timezone processing etc is the same as for that.
713+
714+
:param skeleton: A date time skeleton as defined in the cldr data.
715+
:param datetime: the ``time`` or ``datetime`` object; if `None`, the current
716+
time in UTC is used
717+
:param tzinfo: the time-zone to apply to the time for display
718+
:param locale: a `Locale` object or a locale identifier
719+
"""
720+
locale = Locale.parse(locale)
721+
format = locale.datetime_skeletons[skeleton]
722+
return format_datetime(datetime, format, tzinfo, locale)
723+
724+
697725
TIMEDELTA_UNITS = (
698726
('year', 3600 * 24 * 365),
699727
('month', 3600 * 24 * 30),

scripts/import_cldr.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ def main():
576576
)
577577

578578
datetime_formats = data.setdefault('datetime_formats', {})
579+
datetime_skeletons = data.setdefault('datetime_skeletons', {})
579580
for format in calendar.findall('dateTimeFormats'):
580581
for elem in format.getiterator():
581582
if elem.tag == 'dateTimeFormatLength':
@@ -591,6 +592,10 @@ def main():
591592
datetime_formats = Alias(_translate_alias(
592593
['datetime_formats'], elem.attrib['path'])
593594
)
595+
elif elem.tag == 'availableFormats':
596+
for datetime_skeleton in elem.findall('dateFormatItem'):
597+
datetime_skeletons[datetime_skeleton.attrib['id']] = \
598+
dates.parse_pattern(text_type(datetime_skeleton.text))
594599

595600
# <numbers>
596601

tests/test_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ def test_datetime_formats_property(self):
236236
assert Locale('en').datetime_formats['full'] == u"{1} 'at' {0}"
237237
assert Locale('th').datetime_formats['medium'] == u'{1} {0}'
238238

239+
def test_datetime_skeleton_property(self):
240+
assert Locale('en').datetime_skeletons['Md'].pattern == u"M/d"
241+
assert Locale('th').datetime_skeletons['Md'].pattern == u'd/M'
242+
239243
def test_plural_form_property(self):
240244
assert Locale('en').plural_form(1) == 'one'
241245
assert Locale('en').plural_form(0) == 'other'

tests/test_dates.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,15 @@ def test_format_time():
498498
assert us_east == u'3:30:00 PM Eastern Standard Time'
499499

500500

501+
def test_format_skeleton():
502+
dt = datetime(2007, 4, 1, 15, 30)
503+
assert (dates.format_skeleton('yMEd', dt, locale='en_US') == u'Sun, 4/1/2007')
504+
assert (dates.format_skeleton('yMEd', dt, locale='th') == u'อา. 1/4/2007')
505+
506+
assert (dates.format_skeleton('EHm', dt, locale='en') == u'Sun 15:30')
507+
assert (dates.format_skeleton('EHm', dt, tzinfo=timezone('Asia/Bangkok'), locale='th') == u'อา. 22:30 น.')
508+
509+
501510
def test_format_timedelta():
502511
assert (dates.format_timedelta(timedelta(weeks=12), locale='en_US')
503512
== u'3 months')

0 commit comments

Comments
 (0)