# Copyright (C) 2006-2012 Mortal Coil Games # See LICENSE for details. """ Smart Date Handling """ from twisted.spread import pb import time import datetime from mv3d.util import getarg tzo = 0#int(ConfigItem.GetConfig("TimeZoneOffset", "", 0)) Quarters = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] Months = ["January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] Mon = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] Days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] Dy = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] DaysIn = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] DaysInL = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] def leapyear(y): """ You need to add a docstring here ! """ if y % 4 == 0: if y % 100 != 0 or y % 400 == 0: return 1 return 0 def daysInF(y, m): """ You need to add a docstring here ! """ y += int(m / 12) if leapyear(y): return DaysInL[((m - 1) % 12) + 2] return DaysIn[((m - 1) % 12) + 2] class Date(pb.Copyable, pb.RemoteCopy): """ You need to add a docstring here ! """ def __init__(self): self.d = datetime.datetime(1970, 1, 1, 0, 0) self.ms = 0 def now(self): """ You need to add a docstring here ! """ self.d = self.d.now() self.ms = time.time() self.ms = self.ms - int(self.ms) self.ms *= 1000 return self def set(self, **a): """ You need to add a docstring here ! """ year = getarg(a, "year", 1970) month = getarg(a, "month", 1) day = getarg(a, "day", 1) hour = getarg(a, "hour") minute = getarg(a, "minute") second = getarg(a, "second") self.d = self.d.replace(year, month, day, hour, minute, second) def parse(self, s): """ You need to add a docstring here ! """ if isinstance(s, Date): self.d = s.d return self if isinstance(s, float): import os if os.name == "nt": if s < 0: self.d = self.d.fromtimestamp(0) yr1 = self.d.year mo1 = self.d.month da1 = self.d.day hr1 = self.d.hour mn1 = self.d.minute sc1 = self.d.second self.normalize(yr1, mo1, da1, hr1, mn1, sc1 + s) else: self.d = self.d.fromtimestamp(s) else: self.d = self.d.fromtimestamp(s) self.ms = (s - int(s)) * 1000.0 return self if isinstance(s, int): import os if os.name == "nt": if s < 0: self.d = self.d.fromtimestamp(0) yr1 = self.d.year mo1 = self.d.month da1 = self.d.day hr1 = self.d.hour mn1 = self.d.minute sc1 = self.d.second self.normalize(yr1, mo1, da1, hr1, mn1, sc1 + s) else: self.d = self.d.fromtimestamp(s) else: self.d = self.d.fromtimestamp(s) return self year = 1970 month = 1 day = 1 hour = 0 minute = 0 second = 0 tt = s.split() if len(tt) == 1 and tt[0].isdigit(): self.d = self.d.fromtimestamp(int(tt[0])) return self if len(tt) == 1: if tt[0] == "yesterday": dd = Date() dd.now() dd = dd - (60 * 60 * 24) self.d = dd.d return self if tt[0] == "tomorrow": dd = Date() dd.now() dd = dd + (60 * 60 * 24) self.d = dd.d return self if tt[0] == "now" or tt[0] == "today": self.now() return self if len(tt) > 0 and "/" in tt[0]: d = tt[0].split("/") if len(d) > 2: month = int(d[0]) day = int(d[1]) year = int(d[2]) else: month = int(d[0]) year = int(d[1]) if year < 50: year += 2000 if year < 100: year += 1900 if len(tt) > 0 and "-" in tt[0]: d = tt[0].split("-") if len(d) > 2: month = int(d[0]) day = int(d[1]) year = int(d[2]) else: if d[0].isdigit(): month = int(d[0]) else: # print "Date parse from", s, "failed" assert 0 if d[1].isdigit(): year = int(d[1]) if year < 50: year += 2000 if year < 100: year += 1900 if len(tt) == 2 and ":" in tt[1]: t = tt[1].split(":") hour = int(t[0]) minute = int(t[1]) if len(t) > 2: second = int(t[2]) if len(tt) > 1 and (tt[0] == "last" or tt[0] == "next"): dr = 0 if tt[0] == "last": dr = -1 if tt[0] == "next": dr = 1 if tt[1] == "month": dd = Date() dd.now() dd += [dr, 0, 0] self.d = dd.d return self if tt[1] == "year": dd = Date() dd.now() dd += [0, 0, dr] self.d = dd.d return self if tt[1] == "week": dd = Date() dd.now() dd += [0, 7, 0] self.d = dd.d return self if tt[1].capitalize() in Months or tt[1].capitalize() in Mon: m = 0 for x in range(len(Mon)): if tt[1].capitalize() == Mon[x] or tt[1].capitalize() == Months[x]: m = x dd = Date().now() cm = int(dd.format("%m")) - 1 if dr == 1: dm = m - cm if dm <= 0: dm += 12 dd += [dm, 0, 0] else: dm = cm - m if dm <= 0: dm += 12 dd -= [dm, 0, 0] self.d = dd.d return self if tt[1].capitalize() in Days or tt[1].capitalize() in Dy: m = 0 for x in range(len(Dy)): if tt[1].capitalize() == Dy[x] or tt[1].capitalize() == Days[x]: m = x dd = Date().now() cm = int(dd.format("%w")) - 1 if dr == 1: dm = m - cm if dm <= 0: dm += 7 dd += [0, dm, 0] else: dm = cm - m if dm <= 0: dm += 7 dd -= [0, dm, 0] self.d = dd.d return self self.d = self.d.replace(year, month, day, hour, minute, second) return self def asPOSIXTimestamp(self): return float(self) def stamp(self, c=0): """ You need to add a docstring here ! """ if not c: d = self.d.strftime("%s") if d == "": if self.d.year >= 1970: d = time.mktime((self.d.year, self.d.month, self.d.day, self.d.hour, self.d.minute, self.d.second, int(self.format("%w")), int(self.format("%j")), - 1)) else: yd = 1970 - self.d.year d = time.mktime((self.d.year + yd, self.d.month, self.d.day, self.d.hour, self.d.minute, self.d.second, int(self.format("%w")), int(self.format("%j")), - 1)) d -= (yd * 60 * 60 * 24 * 365)# - 18000 #d=((self.d.year-1970)*(60*60*24*365)+(int(self.format("%j"))-1)*(60*60*24)+(self.d.hour)*60*60+self.d.minute*60+self.d.second) return int(d) return int(self.d.strftime("%s")) - tzo def format(self, fmt="%m/%d/%Y %H:%M:%S"): """ You need to add a docstring here ! """ if "%q" in fmt: fmt.replace("\%q", "%d" % ( ((self.thisquarter()[0] - 1) / 3) + 1) ) return self.d.strftime(fmt) def getquarter(self): """ You need to add a docstring here ! """ return (self.thisquarter()[0] - 1) / 3 + 1 def thisquarter(self): """ You need to add a docstring here ! """ m = int(self.format("%m")) for x in range(0, len(Quarters)): if m in Quarters[x]: return Quarters[x] return [] def getdayofyear(self): """ You need to add a docstring here ! """ return int(self.format("%j")) def getweekofyear(self): """ You need to add a docstring here ! """ return int(self.format("%W")) def getdayofweek(self): """ You need to add a docstring here ! """ return int(self.format("%w")) def normalize(self, yy, mm, dd, hh, mn, ss): """ You need to add a docstring here ! """ while ss < 0: ss += 60 mn -= 1 while ss > 59: ss -= 60 mn += 1 while mn < 0: mn += 60 hh -= 1 while mn > 59: mn -= 60 hh += 1 while hh < 0: hh += 24 dd -= 1 while hh > 23: hh -= 24 dd += 1 while dd < 1: mm -= 1 dd += DaysIn[((mm - 1) % 12) + 1] while dd > DaysIn[((mm - 1) % 12) + 1]: dd -= DaysIn[((mm - 1) % 12) + 1] mm += 1 while mm < 1: mm += 12 yy -= 1 while mm > 12: mm -= 12 yy += 1 return self.parse("%d/%d/%d %d:%d:%d" % (mm, dd, yy, hh, mn, ss)) def __add__(self, a): sum = self.stamp() - tzo ms = self.ms if isinstance(a, float): dd = Date() dd.parse(a) return self + a if isinstance(a, int): sum = a + (self.stamp() - tzo) if isinstance(a, Date): sum = (a.stamp() - tzo) + (self.stamp() - tzo) ms = self.ms + a.ms while ms > 1000: sum += 1 ms -= 1000 if isinstance(a, str): dd = Date() dd.parse(a) return self + dd#sum = (a.stamp() - tzo) + (self.stamp() - tzo) if isinstance(a, list): mm = int(self.format("%m")) dd = int(self.format("%d")) yy = int(self.format("%Y")) hh = int(self.format("%H")) mn = int(self.format("%M")) ss = int(self.format("%S")) if len(a) == 6: ss += a[5] while ss > 59: ss -= 60 mn += 1 while ss < 0: ss += 60 mn -= 1 mn += a[4] while mn > 59: mn -= 60 hh += 1 while mn < 0: mn += 60 hh -= 1 hh += a[3] while hh > 23: hh -= 24 dd += 1 while hh < 0: hh += 24 dd -= 1 if len(a) > 2: dd += a[1] mm += a[0] while dd > DaysIn[((mm - 1) % 12) + 1]: dd -= DaysIn[mm % 12] mm += 1 if mm == 13: mm = 1 yy += 1 while dd < 1: mm -= 1 if mm == 0: mm = 12 yy -= 1 dd += DaysIn[mm % 12] while mm > 12: mm -= 12 yy += 1 while mm < 1: mm += 12 yy -= 1 yy += a[2] da = Date() da.parse("%d/%d/%d %d:%d:%d" % (mm, dd, yy, hh, mn, ss)) return da d = Date() d.parse(sum + tzo) d.ms = ms return d def __sub__(self, a): sum = self.stamp() - tzo ms = 0 if isinstance(a, float): dd = Date() dd.parse(a) return self - a if isinstance(a, int): sum = (self.stamp() - tzo) - a if isinstance(a, Date): sum = (self.stamp() - tzo) - (a.stamp() - tzo) ms = self.ms - a.ms while ms < 0: ms += 1000 sum -= 1 if isinstance(a, str): dd = Date() dd.parse(a) #sum=(self.stamp()-tzo)-(a.stamp()-tzo) return self - dd if isinstance(a, list): mm = int(self.format("%m")) dd = int(self.format("%d")) yy = int(self.format("%Y")) hh = int(self.format("%H")) mn = int(self.format("%M")) ss = int(self.format("%S")) if len(a) == 6: ss -= a[5] while ss < 0: ss += 60 mn -= 1 mn -= a[4] while mn < 0: mn += 60 hh -= 1 hh -= a[3] while hh < 0: hh += 24 dd -= 1 if len(a) > 2: dd -= a[1] while dd < 1: mm -= 1 dd += DaysIn[((mm - 1) % 12) + 1] mm -= a[0] while mm < 1: mm += 12 yy -= 1 yy -= a[2] da = Date() da.parse("%d/%d/%d %d:%d:%d" % (mm, dd, yy, hh, mn, ss)) return da d = Date() d.parse(sum + tzo) d.ms = ms return d def __str__(self): return self.format() def __int__(self): return self.stamp() def __float__(self): return self.stamp() + (self.ms / 1000.0) def __lt__(self, o): if self.stamp() + (self.ms / 1000.0) < Date().parse(o).stamp() + (Date().parse(o).ms / 1000.0): return True return False def __gt__(self, o): if self.stamp() + (self.ms / 1000.0) > Date().parse(o).stamp() + (Date().parse(o).ms / 1000.0): return True return False def __le__(self, o): if self.stamp() + (self.ms / 1000.0) <= Date().parse(o).stamp() + (Date().parse(o).ms / 1000.0): return True return False def __ge__(self, o): if self.stamp() + (self.ms / 1000.0) >= Date().parse(o).stamp() + (Date().parse(o).ms / 1000.0): return True return False def __eq__(self, o): if o == None: return False if self.stamp() + (self.ms / 1000.0) == Date().parse(o).stamp() + (Date().parse(o).ms / 1000.0): return True return False def __ne__(self, o): if self.stamp() + (self.ms / 1000.0) != Date().parse(o).stamp() + (Date().parse(o).ms / 1000.0): return True return False pb.setUnjellyableForClass(Date, Date)