--- a/utils.py Thu May 07 16:33:22 2009 +0200
+++ b/utils.py Thu May 07 16:42:34 2009 +0200
@@ -11,10 +11,10 @@
from datetime import datetime, timedelta, date
from time import time
from random import randint, seed
-
+from calendar import monthrange
+
# initialize random seed from current time
seed()
-
try:
strptime = datetime.strptime
except AttributeError: # py < 2.5
@@ -26,29 +26,70 @@
"""return a date from a date (leaving unchanged) or a datetime"""
if isinstance(somedate, datetime):
return date(somedate.year, somedate.month, somedate.day)
- assert isinstance(somedate, date)
- return date
+ assert isinstance(somedate, date), repr(somedate)
+ return somedate
+
+def todatetime(somedate):
+ """return a date from a date (leaving unchanged) or a datetime"""
+ if isinstance(somedate, date):
+ return datetime(somedate.year, somedate.month, somedate.day)
+ assert isinstance(somedate, datetime), repr(somedate)
+ return somedate
+
+ONEDAY = timedelta(days=1)
+ONEWEEK = timedelta(days=7)
+
+def days_in_month(date_):
+ return monthrange(date_.year, date_.month)[1]
-def date_range(begin, end, incr=1, include=None):
+def previous_month(date_, nbmonth=1):
+ while nbmonth:
+ date_ = first_day(date_) - ONEDAY
+ nbmonth -= 1
+ return date_
+
+def next_month(date_, nbmonth=1):
+ while nbmonth:
+ date_ = last_day(date_) + ONEDAY
+ nbmonth -= 1
+ return date_
+
+def first_day(date_):
+ return date(date_.year, date_.month, 1)
+
+def last_day(date_):
+ return date(date_.year, date_.month, days_in_month(date_))
+
+def date_range(begin, end, incday=None, incmonth=None):
"""yields each date between begin and end
:param begin: the start date
:param end: the end date
:param incr: the step to use to iterate over dates. Default is
- one day.
+ one day.
:param include: None (means no exclusion) or a function taking a
date as parameter, and returning True if the date
should be included.
"""
- incr = timedelta(incr, 0, 0)
- while begin <= end:
- if include is None or include(begin):
+ assert not (incday and incmonth)
+ begin = todate(begin)
+ end = todate(end)
+ if incmonth:
+ while begin < end:
+ begin = next_month(begin, incmonth)
yield begin
- begin += incr
+ else:
+ if not incday:
+ incr = ONEDAY
+ else:
+ incr = timedelta(incday)
+ while begin <= end:
+ yield begin
+ begin += incr
def ustrftime(date, fmt='%Y-%m-%d'):
"""like strftime, but returns a unicode string instead of an encoded
- string which may be problematic with localized date.
-
+ string which' may be problematic with localized date.
+
encoding is guessed by locale.getpreferredencoding()
"""
# date format may depend on the locale
@@ -79,7 +120,7 @@
dict1 = dict(dict1)
dict1.update(dict2)
return dict1
-
+
class SizeConstrainedList(list):
"""simple list that makes sure the list does not get bigger
@@ -120,12 +161,12 @@
def __nonzero__(self):
return True
-
+
def write(self, value):
assert isinstance(value, unicode), u"unicode required not %s : %s"\
% (type(value).__name__, repr(value))
self.append(value)
-
+
def getvalue(self):
return u''.join(self)
@@ -164,8 +205,8 @@
self.add_post_inline_script(u"""jQuery(document).ready(function () {
%s
});""" % jscode)
-
-
+
+
def add_js(self, jsfile):
"""adds `jsfile` to the list of javascripts used in the webpage
@@ -231,18 +272,18 @@
if skiphead:
return header
return u'<head>\n%s</head>\n' % header
-
+
class HTMLStream(object):
"""represents a HTML page.
This is used my main templates so that HTML headers can be added
at any time during the page generation.
-
+
HTMLStream uses the (U)StringIO interface to be compliant with
existing code.
"""
-
+
def __init__(self, req):
# stream for <head>
self.head = req.html_headers