summaryrefslogtreecommitdiff
path: root/src/python/Time.py
blob: d5e092ca5b154bc6a31b5fa1b11aac482a58c076 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/usr/bin/env python
#======================================================================
# FILE: Time.py
# CREATOR: eric
#
# (C) COPYRIGHT 2001, Eric Busboom <eric@civicknowledge.com>
# (C) COPYRIGHT 2001, Patrick Lewis <plewis@inetarena.com>
#
# This library is free software; you can redistribute it and/or modify
# it under the terms of either:
#
#   The LGPL as published by the Free Software Foundation, version
#   2.1, available at: https://www.gnu.org/licenses/lgpl-2.1.txt
#
# Or:
#
#   The Mozilla Public License Version 2.0. You may obtain a copy of
#   the License at https://www.mozilla.org/MPL/
#======================================================================

from LibicalWrap import *
from Property import Property
from types import DictType, StringType, IntType, FloatType
from Duration import Duration

UTC = icaltimezone_get_utc_timezone()

class Time(Property):
    """ Represent iCalendar DATE, TIME and DATE-TIME """
    def __init__(self, arg, name="DTSTART", zone=None):
        """
        Create a new Time from a string or number of seconds past the
        POSIX epoch

        Time("19970325T123000Z")  Construct from an iCalendar string
        Time(8349873494)          Construct from seconds past POSIX epoch

        """
        e1=icalerror_supress("MALFORMEDDATA")
        e2=icalerror_supress("BADARG")

        if isinstance(arg, DictType):
            # Dictionary -- used for creating from Component
            self.tt = icaltime_from_string(arg['value'])
            Property.__init__(self, ref=arg['ref'])
        else:
            if isinstance(arg, StringType):
                # Create from an iCal string
                self.tt = icaltime_from_string(arg)
            elif isinstance(arg, IntType) or   \
                 isinstance(arg, FloatType):
                # Create from seconds past the POSIX epoch
                if zone:
                        self.tt = icaltime_from_timet_with_zone(int(arg),0,icaltimezone_get_builtin_timezone(zone))
                else:
                        self.tt = icaltime_from_timet_with_zone(int(arg),0,icaltimezone_get_utc_timezone())
            elif isinstance(arg, Time):
                # Copy an instance
                self.tt = arg.tt
            else:
                self.tt = icaltime_null_time()

            Property.__init__(self,type=name)

        icalerror_restore("MALFORMEDDATA",e1)
        icalerror_restore("BADARG",e2)

        if icaltime_is_null_time(self.tt):
            raise Property.ConstructorFailedError("Failed to construct a Time")

        try:
            self._update_value()
        except Property.UpdateFailedError:
            raise Property.ConstructorFailedError("Failed to construct a Time")

    def _update_value(self):
        self.normalize()
        self.value(icaltime_as_ical_string(self.tt),"DATE-TIME")

    def valid(self):
        " Returns true if this is a valid time "
        return not icaltime_is_null_time(self.tt)

    def utc_seconds(self,v=None):
        """ Returns or sets time in seconds past POSIX epoch"""
        tz = icaltimezone_get_builtin_timezone(self.timezone())
        if (v!=None):
            self.tt = icaltime_from_timet_with_zone(v,0,tz)
            self._update_value()

        return icaltime_as_timet_with_zone(self.tt, tz)

    def is_utc(self):
        """ Returns a boolean indicating if time is in UTC """
        return icaltime_is_utc(self.tt)

    def is_date(self):
        """ Returns a boolean indicating if time is actually a date """
        return icaltime_is_date(self.tt)

    def timezone(self,v=None):
        """ Returns, set (if none) or alter the timezone for this time """

        origtz = icaltime_get_tzid(self.tt)

        if (v != None):
            assert(isinstance(v,StringType) )
            if (v == "UTC"):
                tz = icaltimezone_get_utc_timezone()
                del self['TZID']
            else:
                tz = icaltimezone_get_builtin_timezone(v)

            if not origtz:
                self.tt = icaltime_set_timezone(self.tt, tz)
            else:
                self.tt = icaltime_convert_to_zone(self.tt,tz)

            if (icaltime_get_tzid(self.tt) != "UTC"):
                self['TZID'] = icaltime_get_tzid(self.tt)

        self._update_value()
        return icaltime_get_tzid(self.tt)

    def normalize(self):
        self.tt = icaltime_normalize(self.tt)

    def __second_property(self,v=None):
        """ Get or set the seconds component of this time """
        if(v != None):
            self.tt.second = v
            self._update_value()
        return self.tt.second
    second = property(__second_property, __second_property)

    def __minute_property(self,v=None):
        """ Get or set the minute component of this time """
        if(v != None):
            self.tt.minute = v
            self._update_value()
        return self.tt.minute
    minute = property(__minute_property, __minute_property)

    def __hour_property(self,v=None):
        """ Get or set the hour component of this time """
        if(v != None):
            self.tt.hour = v
            self._update_value()
        return self.tt.hour
    hour = property(__hour_property, __hour_property)

    def __day_property(self,v=None):
        """ Get or set the month day component of this time """
        if(v != None):
            self.tt.day = v
            self._update_value()
        return self.tt.day
    day = property(__day_property, __day_property)

    def __month_property(self,v=None):
        """ Get or set the month component of this time. January is month 1 """
        if(v != None):
            self.tt.month = v
            self._update_value()
        return self.tt.month
    month = property(__month_property, __month_property)

    def __year_property(self,v=None):
        """ Get or set the year component of this time """
        if(v != None):
            self.tt.year = v
            self._update_value()
        return self.tt.year
    year = property(__year_property, __year_property)


    def __cmp__(self,other):

        if other == None:
            return cmp(self.utc_seconds(),None)

        return cmp(self.utc_seconds(),other.utc_seconds())


    def __add__(self,o):

        other = Duration(o,"DURATION")

        if not other.valid():
            return Duration(0,"DURATION")

        print self.utc_seconds(), other.seconds()
        seconds = self.utc_seconds() + other.seconds()

        new = Time(seconds,self.name(),self.timezone())

        return new

    def __radd_(self,o):
        return self.__add__(o)


    def __sub__(self,o):


        if isinstance(o,Time):
            # Subtract a time from this time and return a duration
            seconds = self.utc_seconds() - o.utc_seconds()
            return Duration(seconds)
        elif isinstance(o,Duration):
            # Subtract a duration from this time and return a time
            other = Duration(o)
            if(not other.valid()):
                return Time()

            seconds = self.utc_seconds() - other.seconds()
            return Time(seconds)
        else:
            raise TypeError, "subtraction with Time requires Time or Duration"