1from __future__ import unicode_literals
2
3# NOTE: t must be INT!!!
4import time
5import datetime
6import warnings
7
8try:
9    from tzlocal import get_localzone
10    LOCAL_ZONE = get_localzone()
11except:  # except all problems...
12    warnings.warn(
13        'Please install or fix tzlocal library (pip install tzlocal) in order to make Date object work better. Otherwise I will assume DST is in effect all the time'
14    )
15
16    class LOCAL_ZONE:
17        @staticmethod
18        def dst(*args):
19            return 1
20
21
22from js2py.base import MakeError
23CUM = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
24msPerDay = 86400000
25msPerYear = int(86400000 * 365.242)
26msPerSecond = 1000
27msPerMinute = 60000
28msPerHour = 3600000
29HoursPerDay = 24
30MinutesPerHour = 60
31SecondsPerMinute = 60
32NaN = float('nan')
33LocalTZA = -time.timezone * msPerSecond
34
35
36def DaylightSavingTA(t):
37    if t is NaN:
38        return t
39    try:
40        return int(
41            LOCAL_ZONE.dst(datetime.datetime.utcfromtimestamp(
42                t // 1000)).seconds) * 1000
43    except:
44        warnings.warn(
45            'Invalid datetime date, assumed DST time, may be inaccurate...',
46            Warning)
47        return 1
48        #raise MakeError('TypeError', 'date not supported by python.datetime. I will solve it in future versions')
49
50
51def GetTimeZoneName(t):
52    return time.tzname[DaylightSavingTA(t) > 0]
53
54
55def LocalToUTC(t):
56    return t - LocalTZA - DaylightSavingTA(t - LocalTZA)
57
58
59def UTCToLocal(t):
60    return t + LocalTZA + DaylightSavingTA(t)
61
62
63def Day(t):
64    return t // 86400000
65
66
67def TimeWithinDay(t):
68    return t % 86400000
69
70
71def DaysInYear(y):
72    if y % 4:
73        return 365
74    elif y % 100:
75        return 366
76    elif y % 400:
77        return 365
78    else:
79        return 366
80
81
82def DayFromYear(y):
83    return 365 * (y - 1970) + (y - 1969) // 4 - (y - 1901) // 100 + (
84        y - 1601) // 400
85
86
87def TimeFromYear(y):
88    return 86400000 * DayFromYear(y)
89
90
91def YearFromTime(t):
92    guess = 1970 - t // 31556908800  # msPerYear
93    gt = TimeFromYear(guess)
94    if gt <= t:
95        while gt <= t:
96            guess += 1
97            gt = TimeFromYear(guess)
98        return guess - 1
99    else:
100        while gt > t:
101            guess -= 1
102            gt = TimeFromYear(guess)
103        return guess
104
105
106def DayWithinYear(t):
107    return Day(t) - DayFromYear(YearFromTime(t))
108
109
110def InLeapYear(t):
111    y = YearFromTime(t)
112    if y % 4:
113        return 0
114    elif y % 100:
115        return 1
116    elif y % 400:
117        return 0
118    else:
119        return 1
120
121
122def MonthFromTime(t):
123    day = DayWithinYear(t)
124    leap = InLeapYear(t)
125    if day < 31:
126        return 0
127    day -= leap
128    if day < 59:
129        return 1
130    elif day < 90:
131        return 2
132    elif day < 120:
133        return 3
134    elif day < 151:
135        return 4
136    elif day < 181:
137        return 5
138    elif day < 212:
139        return 6
140    elif day < 243:
141        return 7
142    elif day < 273:
143        return 8
144    elif day < 304:
145        return 9
146    elif day < 334:
147        return 10
148    else:
149        return 11
150
151
152def DateFromTime(t):
153    mon = MonthFromTime(t)
154    day = DayWithinYear(t)
155    return day - CUM[mon] - (1 if InLeapYear(t) and mon >= 2 else 0) + 1
156
157
158def WeekDay(t):
159    # 0 == sunday
160    return (Day(t) + 4) % 7
161
162
163def msFromTime(t):
164    return t % 1000
165
166
167def SecFromTime(t):
168    return (t // 1000) % 60
169
170
171def MinFromTime(t):
172    return (t // 60000) % 60
173
174
175def HourFromTime(t):
176    return (t // 3600000) % 24
177
178
179def MakeTime(hour, Min, sec, ms):
180    # takes PyJs objects and returns t
181    if not (hour.is_finite() and Min.is_finite() and sec.is_finite()
182            and ms.is_finite()):
183        return NaN
184    h, m, s, milli = hour.to_int(), Min.to_int(), sec.to_int(), ms.to_int()
185    return h * 3600000 + m * 60000 + s * 1000 + milli
186
187
188def MakeDay(year, month, date):
189    # takes PyJs objects and returns t
190    if not (year.is_finite() and month.is_finite() and date.is_finite()):
191        return NaN
192    y, m, dt = year.to_int(), month.to_int(), date.to_int()
193    y += m // 12
194    mn = m % 12
195    d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y) == 366
196                                             and mn >= 2 else 0)
197    return d  # ms per day
198
199
200def MakeDate(day, time):
201    return 86400000 * day + time
202
203
204def TimeClip(t):
205    if t != t or abs(t) == float('inf'):
206        return NaN
207    if abs(t) > 8.64 * 10**15:
208        return NaN
209    return int(t)
210