Skip to content

Commit

Permalink
Fixed import and format_timedelta to handle new time unit patterns in…
Browse files Browse the repository at this point in the history
… cldr-24.

Fixed tests to account for various minor changes in cldr-24.
  • Loading branch information
benselme committed Jan 9, 2015
1 parent 071e38a commit 9327e08
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 28 deletions.
29 changes: 19 additions & 10 deletions babel/dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from __future__ import division

import re
import warnings
import pytz as _pytz

from datetime import date, datetime, time, timedelta
Expand Down Expand Up @@ -705,7 +706,7 @@ def format_time(time=None, format='medium', tzinfo=None, locale=LC_TIME):


def format_timedelta(delta, granularity='second', threshold=.85,
add_direction=False, format='medium',
add_direction=False, format='long',
locale=LC_TIME):
"""Return a time delta according to the rules of the given locale.
Expand Down Expand Up @@ -750,25 +751,34 @@ def format_timedelta(delta, granularity='second', threshold=.85,
positive timedelta will include the information about
it being in the future, a negative will be information
about the value being in the past.
:param format: the format (currently only "medium" and "short" are supported)
:param format: the format (currently only "long" and "short" are supported,
"medium" is deprecated, currently converted to "long" to
maintain compatibility)
:param locale: a `Locale` object or a locale identifier
"""
if format not in ('short', 'medium'):
if format not in ('short', 'medium', 'long'):
raise TypeError('Format can only be one of "short" or "medium"')
if format == 'medium':
warnings.warn('"medium" value for format param of format_timedelta'
' is deprecated. Use "long" instead',
category=DeprecationWarning)
format = 'long'
if isinstance(delta, timedelta):
seconds = int((delta.days * 86400) + delta.seconds)
else:
seconds = delta
locale = Locale.parse(locale)

def _iter_choices(unit):
def _iter_patterns(a_unit):
if add_direction:
unit_rel_patterns = locale._data['date_fields'][a_unit]
if seconds >= 0:
yield unit + '-future'
yield unit_rel_patterns['future']
else:
yield unit + '-past'
yield unit + ':' + format
yield unit
yield unit_rel_patterns['past']
a_unit = 'duration-' + a_unit
yield locale._data['unit_patterns'].get(a_unit + ':' + format)
yield locale._data['unit_patterns'].get(a_unit)

for unit, secs_per_unit in TIMEDELTA_UNITS:
value = abs(seconds) / secs_per_unit
Expand All @@ -778,8 +788,7 @@ def _iter_choices(unit):
value = int(round(value))
plural_form = locale.plural_form(value)
pattern = None
for choice in _iter_choices(unit):
patterns = locale._data['unit_patterns'].get(choice)
for patterns in _iter_patterns(unit):
if patterns is not None:
pattern = patterns[plural_form]
break
Expand Down
27 changes: 19 additions & 8 deletions scripts/import_cldr.py
Original file line number Diff line number Diff line change
Expand Up @@ -609,14 +609,25 @@ def main():
# <units>

unit_patterns = data.setdefault('unit_patterns', {})
for elem in tree.findall('.//units/unit'):
unit_type = elem.attrib['type']
for pattern in elem.findall('unitPattern'):
box = unit_type
if 'alt' in pattern.attrib:
box += ':' + pattern.attrib['alt']
unit_patterns.setdefault(box, {})[pattern.attrib['count']] = \
text_type(pattern.text)
for elem in tree.findall('.//units/unitLength'):
unit_length_type = elem.attrib['type']
for unit in elem.findall('unit'):
unit_type = unit.attrib['type']
for pattern in unit.findall('unitPattern'):
box = unit_type
box += ':' + unit_length_type
unit_patterns.setdefault(box, {})[pattern.attrib['count']] = \
text_type(pattern.text)

date_fields = data.setdefault('date_fields', {})
for elem in tree.findall('.//dates/fields/field'):
field_type = elem.attrib['type']
date_fields.setdefault(field_type, {})
for rel_time in elem.findall('relativeTime'):
rel_time_type = rel_time.attrib['type']
for pattern in rel_time.findall('relativeTimePattern'):
date_fields[field_type].setdefault(rel_time_type, {})\
[pattern.attrib['count']] = text_type(pattern.text)

outfile = open(data_filename, 'wb')
try:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def test_time_formats_property(self):

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}'
assert Locale('th').datetime_formats['medium'] == u'{1} {0}'

def test_plural_form_property(self):
assert Locale('en').plural_form(1) == 'one'
Expand Down
17 changes: 8 additions & 9 deletions tests/test_dates.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,25 +191,25 @@ def test_timezone_name(self):
tz = timezone('Europe/Paris')
dt = datetime(2007, 4, 1, 15, 30, tzinfo=tz)
fmt = dates.DateTimeFormat(dt, locale='fr_FR')
self.assertEqual('Heure : France', fmt['v'])
self.assertEqual('heure : France', fmt['v'])

def test_timezone_location_format(self):
tz = timezone('Europe/Paris')
dt = datetime(2007, 4, 1, 15, 30, tzinfo=tz)
fmt = dates.DateTimeFormat(dt, locale='fr_FR')
self.assertEqual('Heure : France', fmt['VVVV'])
self.assertEqual('heure : France', fmt['VVVV'])

def test_timezone_walltime_short(self):
tz = timezone('Europe/Paris')
t = time(15, 30, tzinfo=tz)
fmt = dates.DateTimeFormat(t, locale='fr_FR')
self.assertEqual('Heure : France', fmt['v'])
self.assertEqual('heure : France', fmt['v'])

def test_timezone_walltime_long(self):
tz = timezone('Europe/Paris')
t = time(15, 30, tzinfo=tz)
fmt = dates.DateTimeFormat(t, locale='fr_FR')
self.assertEqual(u'heure de l\u2019Europe centrale', fmt['vvvv'])
self.assertEqual(u'heure d\u2019Europe centrale', fmt['vvvv'])

def test_hour_formatting(self):
l = 'en_US'
Expand Down Expand Up @@ -265,7 +265,6 @@ def test_with_float(self):
formatted_time = dates.format_time(epoch, format='long', locale='en_US')
self.assertEqual(u'3:30:29 PM +0000', formatted_time)


def test_with_date_fields_in_pattern(self):
self.assertRaises(AttributeError, dates.format_time, date(2007, 4, 1),
"yyyy-MM-dd HH:mm", locale='en_US')
Expand Down Expand Up @@ -305,7 +304,7 @@ def test_direction_adding(self):
string = dates.format_timedelta(timedelta(hours=1),
locale='en',
add_direction=True)
self.assertEqual('In 1 hour', string)
self.assertEqual('in 1 hour', string)
string = dates.format_timedelta(timedelta(hours=-1),
locale='en',
add_direction=True)
Expand Down Expand Up @@ -336,14 +335,14 @@ def test_get_period_names():

def test_get_day_names():
assert dates.get_day_names('wide', locale='en_US')[1] == u'Tuesday'
assert dates.get_day_names('abbreviated', locale='es')[1] == u'mar'
assert dates.get_day_names('abbreviated', locale='es')[1] == u'mar.'
de = dates.get_day_names('narrow', context='stand-alone', locale='de_DE')
assert de[1] == u'D'


def test_get_month_names():
assert dates.get_month_names('wide', locale='en_US')[1] == u'January'
assert dates.get_month_names('abbreviated', locale='es')[1] == u'ene'
assert dates.get_month_names('abbreviated', locale='es')[1] == u'ene.'
de = dates.get_month_names('narrow', context='stand-alone', locale='de_DE')
assert de[1] == u'J'

Expand Down Expand Up @@ -477,7 +476,7 @@ def test_format_time():
t = time(15, 30)
paris = dates.format_time(t, format='full',
tzinfo=timezone('Europe/Paris'), locale='fr_FR')
assert paris == u'15:30:00 heure normale de l\u2019Europe centrale'
assert paris == u'15:30:00 heure normale d\u2019Europe centrale'
us_east = dates.format_time(t, format='full',
tzinfo=timezone('US/Eastern'), locale='en_US')
assert us_east == u'3:30:00 PM Eastern Standard Time'
Expand Down

0 comments on commit 9327e08

Please sign in to comment.