Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions babel/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,19 @@ def datetime_formats(self):
"""
return self._data['datetime_formats']

@property
def datetime_skeletons(self):
"""Locale patterns for formatting parts of a datetime.

>>> Locale('en').datetime_skeletons['MEd']
<DateTimePattern u'E, M/d'>
>>> Locale('fr').datetime_skeletons['MEd']
<DateTimePattern u'E dd/MM'>
>>> Locale('fr').datetime_skeletons['H']
<DateTimePattern u"HH 'h'">
"""
return self._data['datetime_skeletons']

@property
def plural_form(self):
"""Plural rules for the locale.
Expand Down
28 changes: 28 additions & 0 deletions babel/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,34 @@ def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):
return parse_pattern(format).apply(time, locale)


def format_skeleton(skeleton, datetime=None, tzinfo=None, locale=LC_TIME):
r"""Return a time and/or date formatted according to the given pattern.

The skeletons are defined in the CLDR data and provide more flexibility
than the simple short/long/medium formats, but are a bit harder to use.
The are defined using the date/time symbols without order or punctuation
and map to a suitable format for the given locale.

>>> t = datetime(2007, 4, 1, 15, 30)
>>> format_skeleton('MMMEd', t, locale='fr')
u'dim. 1 avr.'
>>> format_skeleton('MMMEd', t, locale='en')
u'Sun, Apr 1'

After the skeleton is resolved to a pattern `format_datetime` is called so
all timezone processing etc is the same as for that.

:param skeleton: A date time skeleton as defined in the cldr data.
:param datetime: the ``time`` or ``datetime`` object; if `None`, the current
time in UTC is used
:param tzinfo: the time-zone to apply to the time for display
:param locale: a `Locale` object or a locale identifier
"""
locale = Locale.parse(locale)
format = locale.datetime_skeletons[skeleton]
return format_datetime(datetime, format, tzinfo, locale)


TIMEDELTA_UNITS = (
('year', 3600 * 24 * 365),
('month', 3600 * 24 * 30),
Expand Down
5 changes: 5 additions & 0 deletions scripts/import_cldr.py
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ def main():
)

datetime_formats = data.setdefault('datetime_formats', {})
datetime_skeletons = data.setdefault('datetime_skeletons', {})
for format in calendar.findall('dateTimeFormats'):
for elem in format.getiterator():
if elem.tag == 'dateTimeFormatLength':
Expand All @@ -591,6 +592,10 @@ def main():
datetime_formats = Alias(_translate_alias(
['datetime_formats'], elem.attrib['path'])
)
elif elem.tag == 'availableFormats':
for datetime_skeleton in elem.findall('dateFormatItem'):
datetime_skeletons[datetime_skeleton.attrib['id']] = \
dates.parse_pattern(text_type(datetime_skeleton.text))

# <numbers>

Expand Down
4 changes: 4 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ def test_datetime_formats_property(self):
assert Locale('en').datetime_formats['full'] == u"{1} 'at' {0}"
assert Locale('th').datetime_formats['medium'] == u'{1} {0}'

def test_datetime_skeleton_property(self):
assert Locale('en').datetime_skeletons['Md'].pattern == u"M/d"
assert Locale('th').datetime_skeletons['Md'].pattern == u'd/M'

def test_plural_form_property(self):
assert Locale('en').plural_form(1) == 'one'
assert Locale('en').plural_form(0) == 'other'
Expand Down
9 changes: 9 additions & 0 deletions tests/test_dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,15 @@ def test_format_time():
assert us_east == u'3:30:00 PM Eastern Standard Time'


def test_format_skeleton():
dt = datetime(2007, 4, 1, 15, 30)
assert (dates.format_skeleton('yMEd', dt, locale='en_US') == u'Sun, 4/1/2007')
assert (dates.format_skeleton('yMEd', dt, locale='th') == u'อา. 1/4/2007')

assert (dates.format_skeleton('EHm', dt, locale='en') == u'Sun 15:30')
assert (dates.format_skeleton('EHm', dt, tzinfo=timezone('Asia/Bangkok'), locale='th') == u'อา. 22:30 น.')


def test_format_timedelta():
assert (dates.format_timedelta(timedelta(weeks=12), locale='en_US')
== u'3 months')
Expand Down