Skip to content

Commit dd467ca

Browse files
committed
Merge pull request #338 from sachinpali146/master
Fix #325 Support more format for timezone
2 parents 3d4b03f + b759308 commit dd467ca

2 files changed

Lines changed: 212 additions & 25 deletions

File tree

babel/dates.py

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -370,20 +370,25 @@ def get_time_format(format='medium', locale=LC_TIME):
370370
return Locale.parse(locale).time_formats[format]
371371

372372

373-
def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME):
373+
def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME, return_z=False):
374374
"""Return the timezone associated with the given `datetime` object formatted
375375
as string indicating the offset from GMT.
376376
377377
>>> dt = datetime(2007, 4, 1, 15, 30)
378378
>>> get_timezone_gmt(dt, locale='en')
379379
u'GMT+00:00'
380-
380+
>>> get_timezone_gmt(dt, locale='en', return_z=True)
381+
'Z'
382+
>>> get_timezone_gmt(dt, locale='en', width='iso8601_short')
383+
u'+00'
381384
>>> tz = get_timezone('America/Los_Angeles')
382385
>>> dt = tz.localize(datetime(2007, 4, 1, 15, 30))
383386
>>> get_timezone_gmt(dt, locale='en')
384387
u'GMT-07:00'
385388
>>> get_timezone_gmt(dt, 'short', locale='en')
386389
u'-0700'
390+
>>> get_timezone_gmt(dt, locale='en', width='iso8601_short')
391+
u'-07'
387392
388393
The long format depends on the locale, for example in France the acronym
389394
UTC string is used instead of GMT:
@@ -395,23 +400,31 @@ def get_timezone_gmt(datetime=None, width='long', locale=LC_TIME):
395400
396401
:param datetime: the ``datetime`` object; if `None`, the current date and
397402
time in UTC is used
398-
:param width: either "long" or "short"
403+
:param width: either "long" or "short" or "iso8601" or "iso8601_short"
399404
:param locale: the `Locale` object, or a locale string
405+
:param return_z: True or False; Function returns indicator "Z"
406+
when local time offset is 0
400407
"""
401408
datetime = _ensure_datetime_tzinfo(_get_datetime(datetime))
402409
locale = Locale.parse(locale)
403410

404411
offset = datetime.tzinfo.utcoffset(datetime)
405412
seconds = offset.days * 24 * 60 * 60 + offset.seconds
406413
hours, seconds = divmod(seconds, 3600)
407-
if width == 'short':
414+
if return_z and hours == 0 and seconds == 0:
415+
return 'Z'
416+
elif seconds == 0 and width == 'iso8601_short':
417+
return u'%+03d' % hours
418+
elif width == 'short' or width == 'iso8601_short':
408419
pattern = u'%+03d%02d'
420+
elif width == 'iso8601':
421+
pattern = u'%+03d:%02d'
409422
else:
410423
pattern = locale.zone_formats['gmt'] % '%+03d:%02d'
411424
return pattern % (hours, seconds // 60)
412425

413426

414-
def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
427+
def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME, return_city=False):
415428
u"""Return a representation of the given timezone using "location format".
416429
417430
The result depends on both the local display name of the country and the
@@ -420,6 +433,10 @@ def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
420433
>>> tz = get_timezone('America/St_Johns')
421434
>>> print(get_timezone_location(tz, locale='de_DE'))
422435
Kanada (St. John’s) Zeit
436+
>>> print(get_timezone_location(tz, locale='en'))
437+
Canada (St. John’s) Time
438+
>>> print(get_timezone_location(tz, locale='en', return_city=True))
439+
St. John’s
423440
>>> tz = get_timezone('America/Mexico_City')
424441
>>> get_timezone_location(tz, locale='de_DE')
425442
u'Mexiko (Mexiko-Stadt) Zeit'
@@ -437,7 +454,10 @@ def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
437454
the timezone; if `None`, the current date and time in
438455
UTC is assumed
439456
:param locale: the `Locale` object, or a locale string
457+
:param return_city: True or False, if True then return exemplar city (location)
458+
for the time zone
440459
:return: the localized timezone name using location format
460+
441461
"""
442462
dt, tzinfo = _get_dt_and_tzinfo(dt_or_tzinfo)
443463
locale = Locale.parse(locale)
@@ -459,7 +479,7 @@ def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
459479
if territory not in locale.territories:
460480
territory = 'ZZ' # invalid/unknown
461481
territory_name = locale.territories[territory]
462-
if territory and len(get_global('territory_zones').get(territory, [])) == 1:
482+
if not return_city and territory and len(get_global('territory_zones').get(territory, [])) == 1:
463483
return region_format % (territory_name)
464484

465485
# Otherwise, include the city in the output
@@ -476,20 +496,24 @@ def get_timezone_location(dt_or_tzinfo=None, locale=LC_TIME):
476496
else:
477497
city_name = zone.replace('_', ' ')
478498

499+
if return_city:
500+
return city_name
479501
return region_format % (fallback_format % {
480502
'0': city_name,
481503
'1': territory_name
482504
})
483505

484506

485507
def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False,
486-
locale=LC_TIME, zone_variant=None):
508+
locale=LC_TIME, zone_variant=None, return_zone=False):
487509
r"""Return the localized display name for the given timezone. The timezone
488510
may be specified using a ``datetime`` or `tzinfo` object.
489511
490512
>>> dt = time(15, 30, tzinfo=get_timezone('America/Los_Angeles'))
491513
>>> get_timezone_name(dt, locale='en_US')
492514
u'Pacific Standard Time'
515+
>>> get_timezone_name(dt, locale='en_US', return_zone=True)
516+
'America/Los_Angeles'
493517
>>> get_timezone_name(dt, width='short', locale='en_US')
494518
u'PST'
495519
@@ -548,6 +572,8 @@ def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False,
548572
values are valid: ``'generic'``, ``'daylight'`` and
549573
``'standard'``.
550574
:param locale: the `Locale` object, or a locale string
575+
:param return_zone: True or False. If true then function
576+
returns long time zone ID
551577
"""
552578
dt, tzinfo = _get_dt_and_tzinfo(dt_or_tzinfo)
553579
locale = Locale.parse(locale)
@@ -572,7 +598,8 @@ def get_timezone_name(dt_or_tzinfo=None, width='long', uncommon=False,
572598

573599
# Get the canonical time-zone code
574600
zone = get_global('zone_aliases').get(zone, zone)
575-
601+
if return_zone:
602+
return zone
576603
info = locale.time_zones.get(zone, {})
577604
# Try explicitly translated zone names first
578605
if width in info:
@@ -1167,7 +1194,7 @@ def __getitem__(self, name):
11671194
return self.format_frac_seconds(num)
11681195
elif char == 'A':
11691196
return self.format_milliseconds_in_day(num)
1170-
elif char in ('z', 'Z', 'v', 'V'):
1197+
elif char in ('z', 'Z', 'v', 'V', 'x', 'X', 'O'):
11711198
return self.format_timezone(char, num)
11721199
else:
11731200
raise KeyError('Unsupported date/time field %r' % char)
@@ -1269,19 +1296,47 @@ def format_milliseconds_in_day(self, num):
12691296
return self.format(msecs, num)
12701297

12711298
def format_timezone(self, char, num):
1272-
width = {3: 'short', 4: 'long'}[max(3, num)]
1299+
width = {3: 'short', 4: 'long', 5: 'iso8601'}[max(3, num)]
12731300
if char == 'z':
12741301
return get_timezone_name(self.value, width, locale=self.locale)
12751302
elif char == 'Z':
1303+
if num == 5:
1304+
return get_timezone_gmt(self.value, width, locale=self.locale, return_z=True)
12761305
return get_timezone_gmt(self.value, width, locale=self.locale)
1306+
elif char == 'O':
1307+
if num == 4:
1308+
return get_timezone_gmt(self.value, width, locale=self.locale)
1309+
# TODO: To add support for O:1
12771310
elif char == 'v':
12781311
return get_timezone_name(self.value.tzinfo, width,
12791312
locale=self.locale)
12801313
elif char == 'V':
12811314
if num == 1:
12821315
return get_timezone_name(self.value.tzinfo, width,
12831316
uncommon=True, locale=self.locale)
1317+
elif num == 2:
1318+
return get_timezone_name(self.value.tzinfo, locale=self.locale, return_zone=True)
1319+
elif num == 3:
1320+
return get_timezone_location(self.value.tzinfo, locale=self.locale, return_city=True)
12841321
return get_timezone_location(self.value.tzinfo, locale=self.locale)
1322+
# Included additional elif condition to add support for 'Xx' in timezone format
1323+
elif char == 'X':
1324+
if num == 1:
1325+
return get_timezone_gmt(self.value, width='iso8601_short', locale=self.locale,
1326+
return_z=True)
1327+
elif num in (2, 4):
1328+
return get_timezone_gmt(self.value, width='short', locale=self.locale,
1329+
return_z=True)
1330+
elif num in (3, 5):
1331+
return get_timezone_gmt(self.value, width='iso8601', locale=self.locale,
1332+
return_z=True)
1333+
elif char == 'x':
1334+
if num == 1:
1335+
return get_timezone_gmt(self.value, width='iso8601_short', locale=self.locale)
1336+
elif num in (2, 4):
1337+
return get_timezone_gmt(self.value, width='short', locale=self.locale)
1338+
elif num in (3, 5):
1339+
return get_timezone_gmt(self.value, width='iso8601', locale=self.locale)
12851340

12861341
def format(self, value, length):
12871342
return ('%%0%dd' % length) % value
@@ -1325,24 +1380,25 @@ def get_week_number(self, day_of_period, day_of_week=None):
13251380

13261381

13271382
PATTERN_CHARS = {
1328-
'G': [1, 2, 3, 4, 5], # era
1329-
'y': None, 'Y': None, 'u': None, # year
1330-
'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter
1331-
'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month
1332-
'w': [1, 2], 'W': [1], # week
1333-
'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day
1334-
'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day
1335-
'a': [1], # period
1336-
'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour
1337-
'm': [1, 2], # minute
1338-
's': [1, 2], 'S': None, 'A': None, # second
1339-
'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4], 'v': [1, 4], 'V': [1, 4] # zone
1383+
'G': [1, 2, 3, 4, 5], # era
1384+
'y': None, 'Y': None, 'u': None, # year
1385+
'Q': [1, 2, 3, 4], 'q': [1, 2, 3, 4], # quarter
1386+
'M': [1, 2, 3, 4, 5], 'L': [1, 2, 3, 4, 5], # month
1387+
'w': [1, 2], 'W': [1], # week
1388+
'd': [1, 2], 'D': [1, 2, 3], 'F': [1], 'g': None, # day
1389+
'E': [1, 2, 3, 4, 5], 'e': [1, 2, 3, 4, 5], 'c': [1, 3, 4, 5], # week day
1390+
'a': [1], # period
1391+
'h': [1, 2], 'H': [1, 2], 'K': [1, 2], 'k': [1, 2], # hour
1392+
'm': [1, 2], # minute
1393+
's': [1, 2], 'S': None, 'A': None, # second
1394+
'z': [1, 2, 3, 4], 'Z': [1, 2, 3, 4, 5], 'O': [1, 4], 'v': [1, 4], # zone
1395+
'V': [1, 2, 3, 4], 'x': [1, 2, 3, 4, 5], 'X': [1, 2, 3, 4, 5] # zone
13401396
}
13411397

13421398
#: The pattern characters declared in the Date Field Symbol Table
13431399
#: (http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table)
13441400
#: in order of decreasing magnitude.
1345-
PATTERN_CHAR_ORDER = "GyYuUQqMLlwWdDFgEecabBChHKkjJmsSAzZvV"
1401+
PATTERN_CHAR_ORDER = "GyYuUQqMLlwWdDFgEecabBChHKkjJmsSAzZOvVXx"
13461402

13471403
_pattern_cache = {}
13481404

0 commit comments

Comments
 (0)