########################################################################
#
# File Name: 		DateFactory.py
#
# Documentation:	http://docs.ftsuite.com/4ODS/DateFactory.py.html
#
"""
Implements the DateFactory interface.
WWW: http://4suite.org/4ODS         e-mail: support@4suite.org

Copyright (c) 1999-2001 Fourthought Inc, USA.   All Rights Reserved.
See  http://4suite.org/COPYRIGHT  for license and copyright information
"""
#"

SECS_IN_DAY = 60*60*24
EPOCH = 1960

class Date:

    def __init__(self,db,data):
        if data is None:
            data = (0,0,0)
        elif len(data) == 2:
            data = map(lambda x:x[0],data[1])
        (self._year,self._month,self._day) = data

        self.value = 0
        for y in range(EPOCH,self._year):
            self.value = self.value + self.__secs_in_year(y)
        for m in range(1,self._month):
            self.value = self.value + self.__secs_in_month(self._year,m)
        self.value = self.value + SECS_IN_DAY*(self._day-1)
            


    def year(self):
        return self._year

    def month(self):
        return self._month

    def day(self):
        return self._day

    def day_of_year(self):
        d = 0
        for m in range(1,self._month):
            d = d + self.__secs_in_month(self._year,m) / SECS_IN_DAY
        return d + self._day

    def month_of_year(self):
        return self.Month.elements[self.month()-1]

    def day_of_week(self):

        ###
        #1960-01-01 is a Friday
        dow = (self.value % 7) - 6
        return self.Weekday.elements[dow]

    def is_leap_year(self):
        from Ft.Ods import DateFactory
        return DateFactory.is_leap_year(self.year())
        
    
    def is_equal(self,a_date):
        return self.value == a_date.value

    def is_greater(self,a_date):
        return self.value > a_date.value

    def is_greater_or_equal(self,a_date):
        return self.value >= a_date.value

    def is_less(self,a_date):
        return self.value < a_date.value

    def is_less_or_equal(self,a_date):
        return self.value <= a_date.value

    def is_between(self,a_date,b_date):
        return self.value >= a_date.value and self.value <= b_date.value

    def next(self,day):
        dow = self.day_of_week()._v
        odow = day._v

        diff = odow - dow
        if diff <= 0:
            diff = diff + 7

        return self.add_days(diff)

    def previous(self,day):
        dow = self.day_of_week()._v
        odow = day._v

        diff = dow - odow
        if diff <= 0:
            diff = diff + 7

        return self.subtract_days(diff)

    def add_days(self,days):
        from Ft.Ods import DateFactory
        return DateFactory.julian_date(self._year,self.day_of_year() + days)

    def subtract_days(self,days):
        from Ft.Ods import DateFactory
        return DateFactory.julian_date(self._year,self.day_of_year() - days)

    def subtract_date(self,a_date):
        return float(self.value - a_date.value) / SECS_IN_DAY
        


    

    def __str__(self):
        return "<Date at %x %s-%s-%s>"% (id(self),self._year,self._month,self._day)

    def __cmp__(self,other):
        if isinstance(other,Date):
            return not (self.year() == other.year() and self.month() == other.month() and self.day() == other.day())
        return 1

    def _4ods_getData(self):
        return (None,((self.year(),),(self.month(),),(self.day(),)))

    def _4ods_isModified(self):
        return 1

    def __secs_in_year(self,year):
        from Ft.Ods import DateFactory
        return (365 + DateFactory.is_leap_year(year)) * SECS_IN_DAY



    def __secs_in_month(self,year,month):
        from Ft.Ods import DateFactory
        return DateFactory.days_in_month(year,Date.Month.elements[month-1]) * SECS_IN_DAY


class WeekdayEnumMember: pass
class WeekdayEnum:
    def lookup(self,st):
        for e in self.elements:
            if e._n == st: return e
        return ''
    class Sunday(WeekdayEnumMember):
        _n = 'Sunday'
        _v = 0
    class Monday(WeekdayEnumMember):
        _n = 'Monday'
        _v = 1
    class Tuesday(WeekdayEnumMember):
        _n = 'Tuesday'
        _v = 2
    class Wednesday(WeekdayEnumMember):
        _n = 'Wednesday'
        _v = 3
    class Thursday(WeekdayEnumMember):
        _n = 'Thursday'
        _v = 4
    class Friday(WeekdayEnumMember):
        _n = 'Friday'
        _v = 5
    class Saturday(WeekdayEnumMember):
        _n = 'Saturday'
        _v = 6

    elements = (Sunday,
                Monday,
                Tuesday,
                Wednesday,
                Thursday,
                Friday,
                Saturday
                )
Date.Weekday = WeekdayEnum()


class MonthEnumMember: pass
class MonthEnum:
    def lookup(self,st):
        for e in self.elements:
            if e._n == st: return e
        return ''
    class January(MonthEnumMember):
        _n = 'January'
        _v = 0
    class February(MonthEnumMember):
        _n = 'February'
        _v = 1
    class March(MonthEnumMember):
        _n = 'March'
        _v = 2
    class April(MonthEnumMember):
        _n = 'April'
        _v = 3
    class May(MonthEnumMember):
        _n = 'May'
        _v = 4
    class June(MonthEnumMember):
        _n = 'June'
        _v = 5
    class July(MonthEnumMember):
        _n = 'July'
        _v = 6
    class August(MonthEnumMember):
        _n = 'August'
        _v = 7
    class September(MonthEnumMember):
        _n = 'September'
        _v = 8
    class October(MonthEnumMember):
        _n = 'October'
        _v = 9
    class November(MonthEnumMember):
        _n = 'November'
        _v = 10
    class December(MonthEnumMember):
        _n = 'December'
        _v = 11

    elements = (January,
                February,
                March,
                April,
                May,
                June,
                July,
                August,
                September,
                October,
                November,
                December
                )
Date.Month = MonthEnum()

    



