1# -*- coding: utf-8 -*- 2import regex as re 3from datetime import datetime, timedelta, tzinfo 4 5from .timezones import timezone_info_list 6 7 8class StaticTzInfo(tzinfo): 9 10 def __init__(self, name, offset): 11 self.__offset = offset 12 self.__name = name 13 14 def tzname(self, dt): 15 return self.__name 16 17 def utcoffset(self, dt): 18 return self.__offset 19 20 def dst(self, dt): 21 return timedelta(0) 22 23 def __repr__(self): 24 return "<%s '%s'>" % (self.__class__.__name__, self.__name) 25 26 def localize(self, dt, is_dst=False): 27 if dt.tzinfo is not None: 28 raise ValueError('Not naive datetime (tzinfo is already set)') 29 return dt.replace(tzinfo=self) 30 31 def __getinitargs__(self): 32 return self.__name, self.__offset 33 34 35def pop_tz_offset_from_string(date_string, as_offset=True): 36 for name, info in _tz_offsets: 37 timezone_re = info['regex'] 38 timezone_match = timezone_re.search(date_string) 39 if timezone_match: 40 start, stop = timezone_match.span() 41 date_string = date_string[:start + 1] + date_string[stop:] 42 return date_string, StaticTzInfo(name, info['offset']) if as_offset else name 43 else: 44 return date_string, None 45 46 47def word_is_tz(word): 48 return bool(_search_regex.match(word)) 49 50 51def convert_to_local_tz(datetime_obj, datetime_tz_offset): 52 return datetime_obj - datetime_tz_offset + local_tz_offset 53 54 55def build_tz_offsets(search_regex_parts): 56 57 def get_offset(tz_obj, regex, repl='', replw=''): 58 return ( 59 tz_obj[0], 60 { 61 'regex': re.compile(re.sub(repl, replw, regex % tz_obj[0]), re.IGNORECASE), 62 'offset': timedelta(seconds=tz_obj[1]) 63 } 64 ) 65 66 for tz_info in timezone_info_list: 67 for regex in tz_info['regex_patterns']: 68 for tz_obj in tz_info['timezones']: 69 search_regex_parts.append(tz_obj[0]) 70 yield get_offset(tz_obj, regex) 71 72 # alternate patterns 73 for replace, replacewith in tz_info.get('replace', []): 74 for tz_obj in tz_info['timezones']: 75 search_regex_parts.append(re.sub(replace, replacewith, tz_obj[0])) 76 yield get_offset(tz_obj, regex, repl=replace, replw=replacewith) 77 78 79def get_local_tz_offset(): 80 offset = datetime.now() - datetime.utcnow() 81 offset = timedelta(days=offset.days, seconds=round(offset.seconds, -1)) 82 return offset 83 84 85_search_regex_parts = [] 86_tz_offsets = list(build_tz_offsets(_search_regex_parts)) 87_search_regex = re.compile('|'.join(_search_regex_parts)) 88local_tz_offset = get_local_tz_offset() 89