From b7593085f38ccee7211972931c9e53d6eee1ceb3 Mon Sep 17 00:00:00 2001 From: Sachin Paliwal Date: Fri, 5 Feb 2016 21:17:55 +0530 Subject: [PATCH] dates: Add iso8601 pattern timezone Format https://github.com/python-babel/babel/issues/325 --- babel/dates.py | 59 +++++++++++++++------ tests/test_dates.py | 123 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+), 15 deletions(-) diff --git a/babel/dates.py b/babel/dates.py index 6d6c36aa..1af9955a 100644 --- a/babel/dates.py +++ b/babel/dates.py @@ -1194,7 +1194,7 @@ class DateTimeFormat(object): return self.format_frac_seconds(num) elif char == 'A': return self.format_milliseconds_in_day(num) - elif char in ('z', 'Z', 'v', 'V'): + elif char in ('z', 'Z', 'v', 'V', 'x', 'X', 'O'): return self.format_timezone(char, num) else: raise KeyError('Unsupported date/time field %r' % char) @@ -1296,11 +1296,17 @@ class DateTimeFormat(object): return self.format(msecs, num) def format_timezone(self, char, num): - width = {3: 'short', 4: 'long'}[max(3, num)] + width = {3: 'short', 4: 'long', 5: 'iso8601'}[max(3, num)] if char == 'z': return get_timezone_name(self.value, width, locale=self.locale) elif char == 'Z': + if num == 5: + return get_timezone_gmt(self.value, width, locale=self.locale, return_z=True) return get_timezone_gmt(self.value, width, locale=self.locale) + elif char == 'O': + if num == 4: + return get_timezone_gmt(self.value, width, locale=self.locale) + # TODO: To add support for O:1 elif char == 'v': return get_timezone_name(self.value.tzinfo, width, locale=self.locale) @@ -1308,7 +1314,29 @@ class DateTimeFormat(object): if num == 1: return get_timezone_name(self.value.tzinfo, width, uncommon=True, locale=self.locale) + elif num == 2: + return get_timezone_name(self.value.tzinfo, locale=self.locale, return_zone=True) + elif num == 3: + return get_timezone_location(self.value.tzinfo, locale=self.locale, return_city=True) return get_timezone_location(self.value.tzinfo, locale=self.locale) + # Included additional elif condition to add support for 'Xx' in timezone format + elif char == 'X': + if num == 1: + return get_timezone_gmt(self.value, width='iso8601_short', locale=self.locale, + return_z=True) + elif num in (2, 4): + return get_timezone_gmt(self.value, width='short', locale=self.locale, + return_z=True) + elif num in (3, 5): + return get_timezone_gmt(self.value, width='iso8601', locale=self.locale, + return_z=True) + elif char == 'x': + if num == 1: + return get_timezone_gmt(self.value, width='iso8601_short', locale=self.locale) + elif num in (2, 4): + return get_timezone_gmt(self.value, width='short', locale=self.locale) + elif num in (3, 5): + return get_timezone_gmt(self.value, width='iso8601', locale=self.locale) def format(self, value, length): return ('%%0%dd' % length) % value @@ -1352,24 +1380,25 @@ class DateTimeFormat(object): PATTERN_CHARS = { - 'G': [1, 2, 3, 4, 5], # era - 'y': None, 'Y': None, 'u': None, # year - 'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter - 'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month - 'w': [1, 2], 'W': [1], # week - 'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day - 'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day - 'a': [1], # period - 'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour - 'm': [1, 2], # minute - 's': [1, 2], 'S': None, 'A': None, # second - 'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4], 'v': [1, 4], 'V': [1, 4] # zone + 'G': [1, 2, 3, 4, 5], # era + 'y': None, 'Y': None, 'u': None, # year + 'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter + 'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month + 'w': [1, 2], 'W': [1], # week + 'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day + 'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day + 'a': [1], # period + 'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour + 'm': [1, 2], # minute + 's': [1, 2], 'S': None, 'A': None, # second + 'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4, 5], 'O': [1, 4], 'v': [1, 4], # zone + 'V': [1, 2, 3, 4], 'x': [1, 2, 3, 4, 5], 'X': [1, 2, 3, 4, 5] # zone } #: The pattern characters declared in the Date Field Symbol Table #: (http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table) #: in order of decreasing magnitude. -PATTERN_CHAR_ORDER = "GyYuUQqMLlwWdDFgEecabBChHKkjJmsSAzZvV" +PATTERN_CHAR_ORDER = "GyYuUQqMLlwWdDFgEecabBChHKkjJmsSAzZOvVXx" _pattern_cache = {} diff --git a/tests/test_dates.py b/tests/test_dates.py index 0d3fe546..5155c0cc 100644 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -250,6 +250,129 @@ class FormatDatetimeTestCase(unittest.TestCase): formatted_string = dates.format_datetime(epoch, format='long', locale='en_US') self.assertEqual(u'April 1, 2012 at 3:30:29 PM +0000', formatted_string) + def test_timezone_formats(self): + dt = datetime(2016, 1, 13, 7, 8, 35) + tz = dates.get_timezone('America/Los_Angeles') + dt = tz.localize(dt) + formatted_string = dates.format_datetime(dt, 'z', locale='en') + self.assertEqual(u'PST', formatted_string) + formatted_string = dates.format_datetime(dt, 'zz', locale='en') + self.assertEqual(u'PST', formatted_string) + formatted_string = dates.format_datetime(dt, 'zzz', locale='en') + self.assertEqual(u'PST', formatted_string) + formatted_string = dates.format_datetime(dt, 'zzzz', locale='en') + self.assertEqual(u'Pacific Standard Time', formatted_string) + formatted_string = dates.format_datetime(dt, 'Z', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZ', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZ', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZZ', locale='en') + self.assertEqual(u'GMT-08:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZZZ', locale='en') + self.assertEqual(u'-08:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'OOOO', locale='en') + self.assertEqual(u'GMT-08:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'VV', locale='en') + self.assertEqual(u'America/Los_Angeles', formatted_string) + formatted_string = dates.format_datetime(dt, 'VVV', locale='en') + self.assertEqual(u'Los Angeles', formatted_string) + formatted_string = dates.format_datetime(dt, 'X', locale='en') + self.assertEqual(u'-08', formatted_string) + formatted_string = dates.format_datetime(dt, 'XX', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXX', locale='en') + self.assertEqual(u'-08:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXXX', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXXXX', locale='en') + self.assertEqual(u'-08:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'x', locale='en') + self.assertEqual(u'-08', formatted_string) + formatted_string = dates.format_datetime(dt, 'xx', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxx', locale='en') + self.assertEqual(u'-08:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxxx', locale='en') + self.assertEqual(u'-0800', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxxxx', locale='en') + self.assertEqual(u'-08:00', formatted_string) + dt = datetime(2016, 1, 13, 7, 8, 35) + tz = dates.get_timezone('UTC') + dt = tz.localize(dt) + formatted_string = dates.format_datetime(dt, 'Z', locale='en') + self.assertEqual(u'+0000', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZ', locale='en') + self.assertEqual(u'+0000', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZ', locale='en') + self.assertEqual(u'+0000', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZZ', locale='en') + self.assertEqual(u'GMT+00:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZZZ', locale='en') + self.assertEqual(u'Z', formatted_string) + formatted_string = dates.format_datetime(dt, 'OOOO', locale='en') + self.assertEqual(u'GMT+00:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'VV', locale='en') + self.assertEqual(u'Etc/GMT', formatted_string) + formatted_string = dates.format_datetime(dt, 'VVV', locale='en') + self.assertEqual(u'GMT', formatted_string) + formatted_string = dates.format_datetime(dt, 'X', locale='en') + self.assertEqual(u'Z', formatted_string) + formatted_string = dates.format_datetime(dt, 'XX', locale='en') + self.assertEqual(u'Z', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXX', locale='en') + self.assertEqual(u'Z', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXXX', locale='en') + self.assertEqual(u'Z', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXXXX', locale='en') + self.assertEqual(u'Z', formatted_string) + formatted_string = dates.format_datetime(dt, 'x', locale='en') + self.assertEqual(u'+00', formatted_string) + formatted_string = dates.format_datetime(dt, 'xx', locale='en') + self.assertEqual(u'+0000', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxx', locale='en') + self.assertEqual(u'+00:00', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxxx', locale='en') + self.assertEqual(u'+0000', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxxxx', locale='en') + self.assertEqual(u'+00:00', formatted_string) + dt = datetime(2016, 1, 13, 7, 8, 35) + tz = dates.get_timezone('Asia/Kolkata') + dt = tz.localize(dt) + formatted_string = dates.format_datetime(dt, 'zzzz', locale='en') + self.assertEqual(u'India Standard Time', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZZ', locale='en') + self.assertEqual(u'GMT+05:30', formatted_string) + formatted_string = dates.format_datetime(dt, 'ZZZZZ', locale='en') + self.assertEqual(u'+05:30', formatted_string) + formatted_string = dates.format_datetime(dt, 'OOOO', locale='en') + self.assertEqual(u'GMT+05:30', formatted_string) + formatted_string = dates.format_datetime(dt, 'VV', locale='en') + self.assertEqual(u'Asia/Calcutta', formatted_string) + formatted_string = dates.format_datetime(dt, 'VVV', locale='en') + self.assertEqual(u'Kolkata', formatted_string) + formatted_string = dates.format_datetime(dt, 'X', locale='en') + self.assertEqual(u'+0530', formatted_string) + formatted_string = dates.format_datetime(dt, 'XX', locale='en') + self.assertEqual(u'+0530', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXX', locale='en') + self.assertEqual(u'+05:30', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXXX', locale='en') + self.assertEqual(u'+0530', formatted_string) + formatted_string = dates.format_datetime(dt, 'XXXXX', locale='en') + self.assertEqual(u'+05:30', formatted_string) + formatted_string = dates.format_datetime(dt, 'x', locale='en') + self.assertEqual(u'+0530', formatted_string) + formatted_string = dates.format_datetime(dt, 'xx', locale='en') + self.assertEqual(u'+0530', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxx', locale='en') + self.assertEqual(u'+05:30', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxxx', locale='en') + self.assertEqual(u'+0530', formatted_string) + formatted_string = dates.format_datetime(dt, 'xxxxx', locale='en') + self.assertEqual(u'+05:30', formatted_string) + class FormatTimeTestCase(unittest.TestCase): -- 2.47.2