@@ -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
485507def 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
13271382PATTERN_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