mylar/lib/js2py/constructors/time_helpers.py

184 lines
4.0 KiB
Python

# 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', Warning)
class LOCAL_ZONE:
@staticmethod
def dst(*args):
return 1
from lib.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)