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