Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added guess_timezone_by_javascript() function

Function is used to identify the timezone by the date string, returned
by JavaScript
  • Loading branch information...
commit 5f618c1e807b638b217f0c998515f6c6e229260e 1 parent bd206f8
@imankulov imankulov authored
Showing with 78 additions and 0 deletions.
  1. +12 −0 timezones/test_timezones.py
  2. +66 −0 timezones/tz_utils.py
View
12 timezones/test_timezones.py
@@ -42,5 +42,17 @@ def test_guess_timezone():
assert tz_utils.guess_timezone_by_ip('127.0.0.1', only_name=True) == None
+def test_guess_timezone_by_javascript():
+ asia_yekaterinburg = tz_utils.get_timezone('Asia/Yekaterinburg')
+ for i in xrange(2): # to ensure that cache breaks nothing
+ assert tz_utils.guess_timezone_by_javascript('Tue Feb 01 2005 00:00:00 GMT+0500 (YEKT)') == asia_yekaterinburg
+ assert tz_utils.guess_timezone_by_javascript('Mon Aug 01 2005 00:00:00 GMT+0600 (YEKST)') == asia_yekaterinburg
+ assert tz_utils.guess_timezone_by_javascript('Mon Aug 01 2005 00:00:00 GMT+0600 (OOOPS)') == None
+
+ assert tz_utils.guess_timezone_by_javascript('Tue Feb 01 2005 00:00:00 GMT+0500 (YEKT)', True) == 'Asia/Yekaterinburg'
+ assert tz_utils.guess_timezone_by_javascript('Mon Aug 01 2005 00:00:00 GMT+0600 (YEKST)', True) == 'Asia/Yekaterinburg'
+ assert tz_utils.guess_timezone_by_javascript('Mon Aug 01 2005 00:00:00 GMT+0600 (OOOPS)', True) == None
+
+
def test_get_timezonez():
assert len(list(zones.get_timezones(only_us=True))) == 8
View
66 timezones/tz_utils.py
@@ -86,6 +86,72 @@ def guess_timezone_by_ip(ip, only_name=False):
return None
+# the map tzname -> timezone string (YEKT -> "Asia/Yekaterinburg",
+# YEKST -> "Asia/Yekaterinburg" and so on)
+_tzname_cache = {}
+
+def guess_timezone_by_javascript(date_string, only_name=False):
+ """Given the `date_string` as returned by JavaScript, tries to return the
+ user browser timezone.
+
+ Example usage::
+
+ from timezones import tz_utils
+ assert tz_utils.guess_timezone_by_javascript('Tue Feb 01 2005 00:00:00 GMT+0500 (YEKT)', only_name=True) == 'Asia/Yekaterinburg'
+
+ You may get the javascript date representation as::
+
+ new Date().toString()
+
+ Implementation note: currently we ignore the tz offset component of the
+ date string object, and rely on the timezone name in parentheses only.
+ """
+
+ def obj_or_name(obj):
+ """ helper function returning timezone object or its name only"""
+ if obj and only_name:
+ return obj.zone
+ return obj
+
+ if not date_string:
+ return None
+
+ chunks = date_string.split()
+ datetime_info = ' '.join(chunks[:5]) # "Tue Feb 01 2005 00:00:00"
+ timezone_info = chunks[5:] # ['GMT+0500', '(YEKT)']
+
+ if len(timezone_info) != 2:
+ return None
+
+ try:
+ dt = datetime.strptime(datetime_info, '%a %b %d %Y %H:%M:%S')
+ except ValueError: # unable to convert string to datetime object
+ return None
+
+ expected_tzname = timezone_info[1].strip('()')
+
+ if expected_tzname in _tzname_cache:
+ # check in cache first (cache stores srings or None`s)
+ timezone_name = _tzname_cache[expected_tzname]
+ if not timezone_name:
+ return None
+ timezone_obj = pytz.timezone(timezone_name)
+ return obj_or_name(timezone_obj)
+
+ for timezone in pytz.all_timezones:
+ timezone_obj = pytz.timezone(timezone)
+ tzname = timezone_obj.tzname(dt)
+ _tzname_cache[tzname] = timezone
+ if tzname == expected_tzname:
+ break
+ else:
+ _tzname_cache[expected_tzname] = None
+ return None
+
+ return obj_or_name(timezone_obj)
+
+
+
def get_timezone(tzname):
"""Get a timezone instance by name or return `None`.
Please sign in to comment.
Something went wrong with that request. Please try again.