# NOTE: t must be INT!!! import time import datetime import warnings try: from tzlocal import get_localzone LOCAL_ZONE = get_localzone() except: # except all problems... warnings.warn('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') class LOCAL_ZONE: @staticmethod def dst(*args): return 1 from js2py.base import MakeError CUM = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) msPerDay = 86400000 msPerYear = int(86400000*365.242) msPerSecond = 1000 msPerMinute = 60000 msPerHour = 3600000 HoursPerDay = 24 MinutesPerHour = 60 SecondsPerMinute = 60 NaN = float('nan') LocalTZA = - time.timezone * msPerSecond def DaylightSavingTA(t): if t is NaN: return t try: return int(LOCAL_ZONE.dst(datetime.datetime.utcfromtimestamp(t//1000)).seconds)*1000 except: warnings.warn('Invalid datetime date, assumed DST time, may be inaccurate...', Warning) return 1 #raise MakeError('TypeError', 'date not supported by python.datetime. I will solve it in future versions') def GetTimeZoneName(t): return time.tzname[DaylightSavingTA(t)>0] def LocalToUTC(t): return t - LocalTZA - DaylightSavingTA(t - LocalTZA) def UTCToLocal(t): return t + LocalTZA + DaylightSavingTA(t) def Day(t): return t//86400000 def TimeWithinDay(t): return t%86400000 def DaysInYear(y): if y%4: return 365 elif y%100: return 366 elif y%400: return 365 else: return 366 def DayFromYear(y): return 365 * (y-1970) + (y-1969)//4 -(y-1901)//100 + (y-1601)//400 def TimeFromYear(y): return 86400000 * DayFromYear(y) def YearFromTime(t): guess = 1970 - t//31556908800 # msPerYear gt = TimeFromYear(guess) if gt<=t: while gt<=t: guess += 1 gt = TimeFromYear(guess) return guess-1 else: while gt>t: guess -= 1 gt = TimeFromYear(guess) return guess def DayWithinYear(t): return Day(t) - DayFromYear(YearFromTime(t)) def InLeapYear(t): y = YearFromTime(t) if y%4: return 0 elif y%100: return 1 elif y%400: return 0 else: return 1 def MonthFromTime(t): day = DayWithinYear(t) leap = InLeapYear(t) if day<31: return 0 day -= leap if day<59: return 1 elif day<90: return 2 elif day<120: return 3 elif day<151: return 4 elif day<181: return 5 elif day<212: return 6 elif day<243: return 7 elif day<273: return 8 elif day<304: return 9 elif day<334: return 10 else: return 11 def DateFromTime(t): mon = MonthFromTime(t) day = DayWithinYear(t) return day-CUM[mon] - (1 if InLeapYear(t) and mon>=2 else 0) + 1 def WeekDay(t): # 0 == sunday return (Day(t) + 4) % 7 def msFromTime(t): return t % 1000 def SecFromTime(t): return (t//1000) % 60 def MinFromTime(t): return (t//60000) % 60 def HourFromTime(t): return (t//3600000) % 24 def MakeTime (hour, Min, sec, ms): # takes PyJs objects and returns t if not (hour.is_finite() and Min.is_finite() and sec.is_finite() and ms.is_finite()): return NaN h, m, s, milli = hour.to_int(), Min.to_int(), sec.to_int(), ms.to_int() return h*3600000 + m*60000 + s*1000 + milli def MakeDay(year, month, date): # takes PyJs objects and returns t if not (year.is_finite() and month.is_finite() and date.is_finite()): return NaN y, m, dt = year.to_int(), month.to_int(), date.to_int() y += m//12 mn = m % 12 d = DayFromYear(y) + CUM[mn] + dt - 1 + (1 if DaysInYear(y)==366 and mn>=2 else 0) return d # ms per day def MakeDate(day, time): return 86400000*day + time def TimeClip(t): if t!=t or abs(t)==float('inf'): return NaN if abs(t) > 8.64 *10**15: return NaN return int(t)