#!/usr/bin/env python from __future__ import print_function import sys import csv from functools import total_ordering from datetime import datetime from operator import attrgetter """Read CSV and make HTML for the conference page. Handles sorting dates, TBD dates, dates in the past, and more. No guarantees that this is bug free :) Author: Christopher Kenna (2012) """ @total_ordering class ConferenceDate(object): TBD_STR = 'tbd' TBD_VAL = 'tbd' def __init__(self, date): if isinstance(date, datetime): self.dt = date else: self.dt = self.date_from_str(date) @classmethod def date_from_str(cls, date_str): try: return datetime.strptime(date_str, '%m/%d/%Y') except ValueError: if cls.TBD_STR == date_str.lower(): return cls.TBD_VAL die('bad date: {0}'.format(date_str)) @classmethod def get_timespan(cls, start, end): ret = [] if start is end: ret.append(cls.html_date(start)) elif (not start.is_tbd() and not end.is_tbd() and start.dt.month == end.dt.month): ret.append(start.dt.strftime('%b. {0}'.format(start.dt.day))) ret.append('–') ret.append(end.dt.strftime('{0}, %Y'.format(end.dt.day))) else: ret.extend([cls.html_date(start), '&endash;', cls.html_date(end)]) return ' '.join(ret) @classmethod def html_date(cls, d): if d.is_tbd(): return 'TBD' # using string format to get '2' and not '02' return d.dt.strftime('%b. {0}, %Y'.format(d.dt.day)) def __eq__(self, other): a_is_tbd, b_is_tbd = self.is_tbd(), other.is_tbd() if a_is_tbd and b_is_tbd: return True elif a_is_tbd or b_is_tbd: return False else: return self.dt == other.dt def __lt__(self, other): a_is_tbd, b_is_tbd = self.is_tbd(), other.is_tbd() if not a_is_tbd and not b_is_tbd: return self.dt < other.dt if not a_is_tbd and b_is_tbd: return True else: # (a_is_tbd and not b_is_tbd) or (a_is_tbd and b_is_tbd) return False def is_tbd(self): return ConferenceDate.TBD_VAL == self.dt def in_past(self): return self < ConferenceDate(datetime.now()) def in_past_style(self): return 'color: red' if self.in_past() else None @total_ordering class Conference(object): def __init__(self, name, url, location, deadline, start, end=None): self.name = name self.url = url self.location = location self.deadline = ConferenceDate(deadline) self.start = ConferenceDate(start) self.end = self.start if end is None else ConferenceDate(end) if self.end < self.start: die('start before end for {0}'.format(self.name)) @classmethod def make_td(cls, contents, style=None): _style = '' if style is not None: _style = ' style="{0}"'.format(style) return '