have dates in URLs be partial timestamps - fix datetime-timezone-comparison mess
--- a/handlers.py Wed Feb 11 23:38:05 2009 +0200
+++ b/handlers.py Thu Feb 12 00:16:52 2009 +0200
@@ -61,6 +61,35 @@
else :
raise http.ResponseError("Unrecognized type: %r" % (type, ))
+def _render_date (request, channel, date, lines, type, count, page, max) :
+ """
+ Render the given LogLines as a http.Response for channel_date
+ """
+
+ # type?
+ if type :
+ # special type
+ return _render_type(request, channel, lines, type)
+
+ else :
+ # format HTML
+ lines = request.prefs['formatter'].format_html(lines)
+
+ # render
+ return templates.render_to_response("channel_date",
+ req = request,
+ prefs = request.prefs,
+ channel = channel,
+ date = date,
+ count = count,
+ page = page,
+ max = max,
+ lines = lines,
+
+ # for prev/next date
+ date_next = channel.source.get_next_date(date),
+ date_prev = channel.source.get_prev_date(date),
+ )
def index (request) :
"""
@@ -143,31 +172,9 @@
# get correct day's correct page of lines
page, max, lines = channel.source.get_date_paged(timestamp, count)
-
- # type?
- if type :
- # special type
- return _render_type(request, channel, lines, type)
- else :
- # format HTML
- lines = formatter.format_html(lines)
-
- # render
- return templates.render_to_response("channel_date",
- req = request,
- prefs = request.prefs,
- channel = channel,
- date = timestamp,
- page = page,
- count = count,
- max = max,
- lines = lines,
-
- # for prev/next date
- date_next = channel.source.get_next_date(timestamp),
- date_prev = channel.source.get_prev_date(timestamp),
- )
+ # render channel_date
+ return _render_date (request, channel, timestamp, lines, type, count, page, max)
@preferences.handler(prefs.timezone)
def channel_calendar (request, channel, year, month, timezone) :
@@ -193,14 +200,14 @@
month = target,
)
-@preferences.handler(prefs.formatter, prefs.timezone, prefs.count)
-def channel_date (request, channel, date, formatter, timezone, count, page=1, type=None) :
+@preferences.handler(prefs.count)
+def channel_date (request, channel, date, count, page=1, type=None) :
"""
Display all log data for the given date
"""
- # fix date timezone
- date = timezone.localize(date)
+# print
+# print "channel_date: date=%s" % date
# get that day's events, either paged or not
if page :
@@ -210,30 +217,8 @@
lines = channel.source.get_date(date)
max = None
- # type?
- if type :
- # special type
- return _render_type(request, channel, lines, type)
-
- else :
- # lines
- lines = formatter.format_html(lines)
-
- # render page
- return templates.render_to_response("channel_date",
- req = request,
- prefs = request.prefs,
- channel = channel,
- date = date,
- page = page,
- count = count,
- max = max,
- lines = lines,
-
- # for prev/next date
- date_next = channel.source.get_next_date(date),
- date_prev = channel.source.get_prev_date(date),
- )
+ # render channel_date
+ return _render_date (request, channel, date, lines, type, count, page, max)
@preferences.handler(prefs.formatter, prefs.count)
def channel_search (request, channel, formatter, count, q=None, page=1, max=1, type=None) :
--- a/helpers.py Wed Feb 11 23:38:05 2009 +0200
+++ b/helpers.py Thu Feb 12 00:16:52 2009 +0200
@@ -46,10 +46,10 @@
def build_date (self, month, mday) :
"""
- Returns a datetime.date for the given (month.year, month.month, mday)
+ Returns a datetime.datetime for the given (month.year, month.month, mday)
"""
- return datetime.date(month.year, month.month, mday)
+ return self.ctx['prefs'][preferences.timezone].localize(datetime.datetime(month.year, month.month, mday))
def now (self) :
"""
@@ -65,13 +65,13 @@
return self.now().date()
- def is_today (self, date) :
+ def is_today (self, dt) :
"""
- Checks if the given date is today
+ Checks if the given datetime.datetime is today
"""
- # construct current date
- return date == self.today()
+ # compare with current date
+ return dt.date() == self.today()
def is_this_month (self, month) :
"""
--- a/log_source.py Wed Feb 11 23:38:05 2009 +0200
+++ b/log_source.py Thu Feb 12 00:16:52 2009 +0200
@@ -384,18 +384,7 @@
self.decoder = decoder
self.filename_fmt = filename_fmt
- def _get_logfile_datetime (self, dt) :
- """
- Get the logfile corresponding to the given datetime
- """
-
- # convert to target timezone
- dtz = dt.astimezone(self.tz)
-
- # convert to date and use that
- return self._get_logfile_date(dtz.date())
-
- def _get_logfile_date (self, d, load=True, mtime=False, ignore_missing=True) :
+ def _get_logfile_date (self, d, load=True, mtime=False, ignore_missing=False) :
"""
Get the logfile corresponding to the given naive date in our timezone.
@@ -443,6 +432,13 @@
reverse the dates are returned in reverse order instead. Note that the meaning of after/until doesn't change
"""
+ # convert timestamps to our timezone's dates
+ if after :
+ after = after.astimezone(self.tz).date()
+
+ if until :
+ until = until.astimezone(self.tz).date()
+
# listdir
filenames = os.listdir(self.path)
@@ -453,7 +449,8 @@
for filename in filenames :
try :
# parse date
- date = self.tz.localize(datetime.datetime.strptime(filename, self.filename_fmt))
+ dt = self.tz.localize(datetime.datetime.strptime(filename, self.filename_fmt))
+ date = dt.date()
except :
# ignore
@@ -465,11 +462,8 @@
continue
else :
-# print
-# print "iter_logfile_dates: after=%s, until=%s, reverse=%s -> %s" % (after, until, reverse, date)
-
# yield
- yield date
+ yield dt
def _iter_date_reverse (self, dt=None) :
"""
@@ -517,7 +511,7 @@
logfile = None
file_count += 1
- logfile = self._get_logfile_date(day)
+ logfile = self._get_logfile_date(day, ignore_missing=True)
# no logfile there?
if not logfile :
@@ -586,18 +580,15 @@
# open that log
logfile = self._get_logfile_date(d_begin)
- if not logfile :
- raise Exception("No logfile for date=%r" % (dt, ))
-
# return the full data
return logfile.read_full()
# otherwise, we need to pull two partial logs
else :
- # open both of them
+ # open both of them, but it's okay if we don't have the second one
f_begin = self._get_logfile_date(d_begin)
- f_end = self._get_logfile_date(d_end)
-
+ f_end = self._get_logfile_date(d_end, ignore_missing=True)
+
# chain together the two sources
return itertools.chain(
f_begin.read_from(dtz_begin),
@@ -634,7 +625,7 @@
log_date = dt.astimezone(self.tz).date()
# test for it
- if self._get_logfile_date(log_date, load=False) :
+ if self._get_logfile_date(log_date, load=False, ignore_missing=True) :
# valid
yield dt.date()
@@ -648,7 +639,7 @@
# compare against dt?
if dt :
# stat
- mtime = self._get_logfile_date(log_date, load=False, mtime=True)
+ mtime = self._get_logfile_date(log_date, load=False, mtime=True, ignore_missing=True)
# not modified?
if mtime < dt :
@@ -656,7 +647,7 @@
continue
# open
- logfile = self._get_logfile_date(log_date, ignore_missing=False)
+ logfile = self._get_logfile_date(log_date)
# yield all lines
for line in logfile.read_full() :
--- a/templates/channel_calendar.tmpl Wed Feb 11 23:38:05 2009 +0200
+++ b/templates/channel_calendar.tmpl Thu Feb 12 00:16:52 2009 +0200
@@ -44,9 +44,9 @@
## build date
<% date = h.build_date(month, day) %>\
## render cell
- <td${' id="today"' if h.is_today(date) else ''}${' class="empty"' if date not in log_dates else ''}>\
+ <td${' id="today"' if h.is_today(date) else ''}${' class="empty"' if date.date() not in log_dates else ''}>\
## link to logs for this day?
- % if date in log_dates :
+ % if date.date() in log_dates :
<a href="${urls.channel_date.build(req, channel=channel, date=date)}">${day}</a>\
% else :
${day}\
--- a/utils.py Wed Feb 11 23:38:05 2009 +0200
+++ b/utils.py Thu Feb 12 00:16:52 2009 +0200
@@ -35,9 +35,12 @@
class URLDateType (URLType) :
"""
- Handle dates in URLs as naive datetime objects (with indeterminate time info)
+ Handle dates in URLs as shortened UTC datetime timestamps
"""
+ # percision = hour
+ SCALE = 60 * 60
+
def __init__ (self, date_fmt) :
"""
Format/parse dates using the given format
@@ -45,19 +48,27 @@
self.date_fmt = date_fmt
- def parse (self, date_str) :
+ def parse (self, sts_str) :
"""
- date_str -> naive datetime.datetime
+ short_timestamp_str -> datetime.datetime
"""
- return datetime.datetime.strptime(date_str, self.date_fmt)
+ # scale -> from_utc + return
+ return from_utc_timestamp(int(sts_str) * self.SCALE)
- def build (self, date) :
+ def build (self, dtz) :
"""
- datetime.date -> date_str
+ datetime.datetime -> short_timestamp_str
"""
- return date.strftime(self.date_fmt)
+ # force it to be interpreted as UTC
+ dt_utc = dtz.replace(tzinfo=pytz.utc)
+
+ # scale the UTC timestamp
+ sts = to_utc_timestamp(dt_utc) / self.SCALE
+
+ # str
+ return str(sts)
class URLTimestampType (URLType) :
"""