datelist.py
'''\
Date List.
classes:
datelist
datelistiter
Developer@Sonnack.com
April 2012
'''
from sys import stdin, stdout, stderr, argv
from datetime import date, datetime, timedelta
from re import compile as RegEx
from logger import logger
FLog = logger('datelist')
class DateParser (object):
'''Date Parser class. Converts various date strings to datetime objects.'''
date_pattern = r'\s\d?\d:\d\d(:\d\d)?'
ptime_fmts = [
'%m/%d/%Y' ,
'%m-%d-%Y' ,
'%m.%d.%Y' ,
'%m/%d/%Y %H:%M:%S' ,
'%m/%d/%Y %H:%M' ,
'%m-%d-%Y %H:%M:%S' ,
'%m-%d-%Y %H:%M' ,
'%d %b %Y %H:%M:%S' ,
'%d %b %Y %H:%M' ,
'%a, %d %b %Y %H:%M:%S' ,
'%a, %d %b %Y %H:%M' ,
'%m/%d/%y %H:%M:%S' ,
'%m/%d/%y %H:%M' ,
'%m-%d-%y %H:%M:%S' ,
'%m-%d-%y %H:%M' ,
'%d %b %y %H:%M:%S' ,
'%d %b %y %H:%M' ,
'%a, %d %b %y %H:%M:%S' ,
'%a, %d %b %y %H:%M' ]
def __init__ (self):
'''Create new DateParser instance.'''
self.matcher = RegEx(self.date_pattern)
def parse (self, date_string):
'''Parse a date string; return a datetime, if possible, else None.'''
m = self.matcher.search(date_string)
if m:
tm = date_string[:m.end()]
for ix,fmt in enumerate(self.ptime_fmts):
try:
dt = datetime.strptime(tm, fmt)
return dt
except:
FLog.trace('###Parse Date### "%s" (attempt #%d: "%s")' % (date_string, 1+ix, fmt))
FLog.error('###Unable to Parse Date### "%s"' % date_string)
else:
FLog.error('###Unknown Date Format### "%s"' % date_string)
return None
class datelist (object):
'''\
Date List Class.
properties:
.dt0 - first date
.dt1 - last date
.td - date difference
methods:
as_list() - get a List of Dates
as_tuple() - get a Tuple of Dates
obj[n] - get nth date in range
iter(obj) - get a date range iterator
len(obj) - date difference in days
str(obj) - printable date range string
repr(obj) - JSON-like string
'''
def __init__ (self, date0, date1=date.today()):
'''Create a new datelist instance.'''
if date1 < date0:
self.dt0 = date1
self.dt1 = date0
else:
self.dt0 = date0
self.dt1 = date1
self.td = timedelta(1) + (self.dt1 - self.dt0)
def as_list (self):
return list(self)
def as_tuple (self):
return tuple(self)
def __cmp__ (self, other):
return cmp(self.dt0, other.dt0) or cmp(self.dt1, other.dt1)
def __len__ (self):
'''Get number of days in range.'''
return self.td.days
def __getitem__ (self, ix):
'''Get Nth Date in range.'''
if (ix < 0) or (len(self) <= ix):
raise IndexError, 'Index out of range: %d' % ix
if ix == 0:
return self.dt0
if ix == (len(self) - 1):
return self.dt1
return self.dt0 + timedelta(ix)
def __iter__ (self):
'''Get a datelist iterator '''
return datelistiter(self)
def __str__ (self):
'''Return a printable date range string.'''
y0 = self.dt0.year
m0 = self.dt0.month
d0 = self.dt0.day
y1 = self.dt1.year
m1 = self.dt1.month
d1 = self.dt1.day
ss = '' if len(self) == 1 else 's'
return '[%d/%d/%d to %d/%d/%d (%d day%s)]' % (m0,d0,y0, m1,d1,y1, len(self), ss)
def __repr__ (self):
'''Return a serializeable JSON object.'''
return '{datelist:{dt0:"%s", dt1:"%s"}}' % (self.dt0, self.dt1)
class datelistiter (object):
'''\
Date List Iterator Class.
properties:
.dt0 - first date (increases towards .dt1)
.dt1 - last date
.dtd - date increment (one day)
methods:
next(obj) - get next item
iter(obj) - get self
'''
def __init__ (self, _datelist):
self.dt0 = _datelist.dt0
self.dt1 = _datelist.dt1
self.dtd = timedelta(1)
def next (self):
if self.dt1 < self.dt0:
raise StopIteration
dt = self.dt0
self.dt0 = self.dt0 + self.dtd
return dt
def __iter__ (self):
return self
'''eof'''