3 # Copyright (C) 2001 Free Software Foundation, Inc.
7 import os
, os
.path
, sys
, re
, time
, string
21 def NumberDaysYear(year
):
22 return 365 + IsLeapYear(year
)
24 def NumberDaysMonth(month
= None, year
= None):
26 m
= time
.localtime()[1]
31 y
= time
.localtime()[0]
40 elif m
in (1, 3, 5, 7, 8, 10, 12):
70 #The slots in a Date object are constrained to allow more efficient operations.
71 __slots__
= ["year", "month", "day"]
73 def __init__(self
, tm
= None):
74 """The initializer has an optional argument, time, in the time module format,
75 wether as in seconds since the epoch (Unix time) wether as a tuple (time tuple).
76 If it is not provided, then it returns the current date."""
80 if isinstance(tm
, int):
81 t
= time
.localtime(tm
)
85 self
.year
, self
.month
, self
.day
= t
[:3]
88 """Returns the weekday of the date.
90 The format is as in the time module: Monday is 0 and sunday is 6."""
91 a
= (14 - self
.month
)//12
93 m
= self
.month
+ 12*a
-2
94 d
= (self
.day
+ y
+ y
//4 - y
//100 + y
//400 + (31*m
//12))%7
102 return "%s, %d-%s-%d" % (Date
.Weekdays
[self
.weekday()],
104 Date
.Months
[self
.month
- 1],
108 """Deep copy of Date objects."""
110 ret
.year
, ret
.month
, ret
.day
= self
.year
, self
.month
, self
.day
113 #The iterator protocol. The iteration is "destructive", like in files.
118 #Last day of the month.
119 if self
.day
== NumberDaysMonth(self
.month
, self
.year
):
130 #Extended iterator protocol. One can go backwards.
132 #First day of the month.
140 self
.day
= NumberDaysMonth(self
.month
, self
.year
)
145 def __eq__(self
, date
):
146 return self
.year
== date
.year
and self
.month
== date
.month
and\
149 def __lt__(self
, other
):
150 return (self
.year
, self
.month
, self
.day
) < (other
.year
, other
.month
, other
.day
)
152 def __le__(self
, other
):
153 return (self
.year
, self
.month
, self
.day
) <= (other
.year
, other
.month
, other
.day
)
155 #Dates can be used as keys in dictionaries.
157 return hash((self
.year
, self
.month
, self
.day
))
159 #Some useful methods.
160 def GetYearDay(self
):
161 """Returns the year day of a date."""
163 for month
in range(1, self
.month
):
164 ret
+= NumberDaysMonth(month
, self
.year
)
167 def DaysToEndYear(self
):
168 """Returns the number of days until the end of the year."""
169 ret
= NumberDaysMonth(self
.month
, self
.year
) - self
.day
170 for i
in range(self
.month
+ 1, 13):
171 ret
+= NumberDaysMonth(i
, self
.year
)
174 def GetWeekday(self
):
175 """Returns the weekday of the date in string format."""
176 return Date
.Weekdays
[self
.weekday()]
179 """Returns the month of the date in string format."""
180 return Date
.Months
[self
.month
- 1]
182 def ToJDNumber(self
):
183 """Returns the Julian day number of a date."""
184 a
= (14 - self
.month
)//12
185 y
= self
.year
+ 4800 - a
186 m
= self
.month
+ 12*a
- 3
187 return self
.day
+ ((153*m
+ 2)//5) + 365*y
+ y
//4 - y
//100 + y
//400 - 32045
190 def __add__(self
, n
):
191 """Adds a (signed) number of days to the date."""
192 if isinstance(n
, int):
193 #Calculate julian day number and add n.
194 temp
= self
.ToJDNumber() + n
195 #Convert back to date format.
196 return DateFromJDNumber(temp
)
198 raise TypeError, "%s is not an integer." % str(n
)
200 def __sub__(self
, date
):
201 """Returns the (signed) difference of days between the dates."""
202 #If it is an integer defer calculation to the __add__ method.
203 if isinstance(date
, int):
204 return self
.__add
__(-date
)
205 elif isinstance(date
, Date
):
206 #Case: The years are equal.
207 if self
.year
== date
.year
:
208 return self
.GetYearDay() - date
.GetYearDay()
211 ret
= self
.DaysToEndYear() + date
.GetYearDay()
212 for year
in range(self
.year
+ 1, date
.year
):
213 ret
+= NumberDaysYear(year
)
216 ret
= date
.DaysToEndYear() + self
.GetYearDay()
217 for year
in range(date
.year
+ 1, self
.year
):
218 ret
+= NumberDaysYear(year
)
221 raise TypeError, "%s is neither an integer nor a Date." % str(date
)
223 #Adding an integer is "commutative".
224 def __radd__(self
, n
):
225 return self
.__add
__(n
)
228 def ToTimeTuple(self
):
229 """Convert a date into a time tuple (time module) corresponding to the
230 same day with the midnight hour."""
231 ret
= [self
.year
, self
.month
, self
.day
]
232 ret
.extend([0, 0, 0])
233 ret
.append(self
.weekday())
234 ret
.extend([self
.GetYearDay(), 0])
238 def needparsep(fname
):
242 if re
.search("^([0-9]{4})\.([0-9]+)\.([0-9]+)$", fname
):
243 if curdate
<= Date(time
.strptime(fname
, "%Y.%m.%d")):
250 def needtransferp(line
):
252 if re
.search("^\s*([0-9]+:[0-9]+)\s*(.+)", line
):
257 if __name__
== "__main__":
260 dirname
= sys
.argv
[1]
262 dirname
= "~/emacs/plans"
264 filelist
= filter(needparsep
, os
.listdir(os
.path
.expanduser(dirname
)))
267 for filename
in filelist
:
268 thatdate
= Date(time
.strptime(filename
, "%Y.%m.%d"))
269 thatdate
= repr(thatdate
.month
)+"/"+repr(thatdate
.day
)+"/"+repr(thatdate
.year
)
271 selected
= filter(needtransferp
, open(os
.path
.join(os
.path
.expanduser(dirname
), filename
), "r"))
272 for line
in selected
:
273 m
= re
.search("^\s*([0-9]+:[0-9]+)\s*\|\s*([0-9]+:[0-9]+)\s*\|\s*(.+)", line
)
275 outputstr
= thatdate
+" "+m
.group(1)+"-"+m
.group(2)+" "+m
.group(3)
277 m
= re
.search("^\s*([0-9]+:[0-9]+)\s*\|\s*(.+?)(\s+\(([0-9]+:[0-9]+)\))?\s*$", line
)
280 duration
= m
.group(4)
281 s
= re
.search("([0-9]+):([0-9]+)", start
)
282 starthour
= int(s
.group(1))
283 startmin
= int(s
.group(2))
284 s
= re
.search("([0-9]+):([0-9]+)", duration
)
285 min = startmin
+int(s
.group(2))
286 hour
= starthour
+int(s
.group(1))
292 min = string
.zfill(repr(min), 2)
293 hour
= string
.zfill(repr(hour
), 2)
294 outputstr
= thatdate
+" "+m
.group(1)+"-"+hour
+":"+min+" "+m
.group(2)
296 outputstr
= thatdate
+" "+m
.group(1)+" "+m
.group(2)