155 lines
6.1 KiB
Python
155 lines
6.1 KiB
Python
import time
|
|
from datetime import datetime, timedelta, tzinfo
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from toontown.toonbase import TTLocalizer
|
|
|
|
|
|
class ToontownTimeZone(tzinfo):
|
|
"""
|
|
A simple implementation of US/Pacific time (UTC-08:00) that is only able to calculate
|
|
correct DST for dates post-2006, which is perfectly acceptable for our use case.
|
|
"""
|
|
offset = -8
|
|
dstBegin = datetime(1, 3, 8, 2) # DST begins on the second Sunday of March.
|
|
dstEnd = datetime(1, 11, 1, 1) # DST ends on the first Sunday of November.
|
|
names = ('PST', 'PDT')
|
|
|
|
@staticmethod
|
|
def forwardToSunday(dt):
|
|
daysToGo = 6 - dt.weekday()
|
|
if daysToGo:
|
|
dt += timedelta(daysToGo)
|
|
|
|
return dt
|
|
|
|
def dst(self, dt):
|
|
# Determine if DST is active for the dt.
|
|
beginning = self.forwardToSunday(self.dstBegin.replace(year=dt.year))
|
|
ending = self.forwardToSunday(self.dstEnd.replace(year=dt.year))
|
|
if beginning <= dt.replace(tzinfo=None) < ending:
|
|
return timedelta(hours=1)
|
|
else:
|
|
return timedelta(0)
|
|
|
|
def utcoffset(self, dt):
|
|
offset = timedelta(hours=self.offset)
|
|
offset += self.dst(dt)
|
|
return offset
|
|
|
|
def tzname(self, dt):
|
|
standardName, dstName = self.names
|
|
if self.dst(dt):
|
|
return dstName
|
|
else:
|
|
return standardName
|
|
|
|
|
|
class UTC(tzinfo):
|
|
"""
|
|
A very simple UTC implementation.
|
|
"""
|
|
|
|
def utcoffset(self, dt):
|
|
return timedelta(0)
|
|
|
|
def tzname(self, dt):
|
|
return 'UTC'
|
|
|
|
def dst(self, dt):
|
|
return timedelta(0)
|
|
|
|
|
|
class ToontownTimeManager:
|
|
notify = DirectNotifyGlobal.directNotify.newCategory('ToontownTimeManager')
|
|
ClockFormat = '%I:%M:%S %p'
|
|
formatStr = '%Y-%m-%d %H:%M:%S'
|
|
|
|
def __init__(self, serverTimeUponLogin = 0, clientTimeUponLogin = 0, globalClockRealTimeUponLogin = 0):
|
|
try:
|
|
self.serverTimeZoneString = base.config.GetString('server-timezone', TTLocalizer.TimeZone)
|
|
except:
|
|
try:
|
|
self.serverTimeZoneString = simbase.config.GetString('server-timezone', TTLocalizer.TimeZone)
|
|
except:
|
|
notify.error('ToontownTimeManager does not have access to base or simbase.')
|
|
|
|
if self.serverTimeZoneString == 'US/Pacific':
|
|
self.serverTimeZone = ToontownTimeZone()
|
|
else:
|
|
self.notify.error('Time Zone %s is not supported.' % self.serverTimeZoneString)
|
|
|
|
self.updateLoginTimes(serverTimeUponLogin, clientTimeUponLogin, globalClockRealTimeUponLogin)
|
|
self.debugSecondsAdded = 0
|
|
|
|
def updateLoginTimes(self, serverTimeUponLogin, clientTimeUponLogin, globalClockRealTimeUponLogin):
|
|
self.serverTimeUponLogin = serverTimeUponLogin
|
|
self.clientTimeUponLogin = clientTimeUponLogin
|
|
self.globalClockRealTimeUponLogin = globalClockRealTimeUponLogin
|
|
self.serverDateTime = datetime.fromtimestamp(self.serverTimeUponLogin, self.serverTimeZone)
|
|
|
|
def getCurServerDateTime(self):
|
|
secondsPassed = globalClock.getRealTime() - self.globalClockRealTimeUponLogin + self.debugSecondsAdded
|
|
curDateTime = (self.serverDateTime + timedelta(seconds=secondsPassed)).astimezone(self.serverTimeZone)
|
|
return curDateTime
|
|
|
|
def getRelativeServerDateTime(self, timeOffset):
|
|
secondsPassed = globalClock.getRealTime() - self.globalClockRealTimeUponLogin + self.debugSecondsAdded
|
|
secondsPassed += timeOffset
|
|
curDateTime = (self.serverDateTime + timedelta(seconds=secondsPassed)).astimezone(self.serverTimeZone)
|
|
return curDateTime
|
|
|
|
def getCurServerDateTimeForComparison(self):
|
|
secondsPassed = globalClock.getRealTime() - self.globalClockRealTimeUponLogin + self.debugSecondsAdded
|
|
curDateTime = self.serverDateTime + timedelta(seconds=secondsPassed)
|
|
curDateTime = curDateTime.replace(tzinfo=self.serverTimeZone)
|
|
return curDateTime
|
|
|
|
def getCurServerTimeStr(self):
|
|
curDateTime = self.getCurServerDateTime()
|
|
result = curDateTime.strftime(self.ClockFormat)
|
|
if result[0] == '0':
|
|
result = result[1:]
|
|
return result
|
|
|
|
def setDebugSecondsAdded(self, moreSeconds):
|
|
self.debugSecondsAdded = moreSeconds
|
|
|
|
def debugTest(self):
|
|
startTime = datetime.today()
|
|
serverTzInfo = self.serverTimeZone
|
|
startTime = startTime.replace(tzinfo=serverTzInfo)
|
|
self.notify.info('startTime = %s' % startTime)
|
|
serverTime = self.getCurServerDateTime()
|
|
self.notify.info('serverTime = %s' % serverTime)
|
|
result = startTime <= serverTime
|
|
self.notify.info('start < serverTime %s' % result)
|
|
startTime1MinAgo = startTime + timedelta(minutes=-1)
|
|
self.notify.info('startTime1MinAgo = %s' % startTime1MinAgo)
|
|
result2 = startTime1MinAgo <= serverTime
|
|
self.notify.info('startTime1MinAgo < serverTime %s' % result2)
|
|
serverTimeForComparison = self.getCurServerDateTimeForComparison()
|
|
self.notify.info('serverTimeForComparison = %s' % serverTimeForComparison)
|
|
result3 = startTime1MinAgo <= serverTimeForComparison
|
|
self.notify.info('startTime1MinAgo < serverTimeForComparison %s' % result3)
|
|
|
|
def convertStrToToontownTime(self, dateStr):
|
|
curDateTime = self.getCurServerDateTime()
|
|
try:
|
|
curDateTime = datetime.fromtimestamp(time.mktime(time.strptime(dateStr, self.formatStr)), self.serverTimeZone)
|
|
except:
|
|
self.notify.warning('error parsing date string=%s' % dateStr)
|
|
|
|
result = curDateTime
|
|
return result
|
|
|
|
def convertUtcStrToToontownTime(self, dateStr):
|
|
curDateTime = self.getCurServerDateTime()
|
|
try:
|
|
timeTuple = time.strptime(dateStr, self.formatStr)
|
|
utcDateTime = datetime(timeTuple[0], timeTuple[1], timeTuple[2], timeTuple[3], timeTuple[4], timeTuple[5], timeTuple[6], UTC())
|
|
curDateTime = utcDateTime.astimezone(self.serverTimeZone)
|
|
except:
|
|
self.notify.warning('error parsing date string=%s' % dateStr)
|
|
|
|
result = curDateTime
|
|
return result
|