Source code for uw.local.termtools

import datetime

from functools import total_ordering

from uw.web.html.form import render_select, render_date_selector_2, render_time_selector_2

seasons = {1: "Winter", 5: "Spring", 9: "Fall"}

[docs]@total_ordering class Term (object): """Class representing UW terms. Terms can be converted to and from term codes, written as text strings or as integers. Methods are available to print useful representations of terms and perform arithmetic on them. """ def __init__ (self, sequence): self.__sequence = sequence def __repr__ (self): return "<Term %04d>" % self.numericCode () def __str__ (self): return self.code () def __eq__ (self, other): if isinstance (other, Term): return self.__sequence == other.__sequence else: return False def __lt__ (self, other): if isinstance (other, Term): return self.__sequence < other.__sequence else: return True def __hash__ (self): return self.__sequence def __add__ (self, other): return Term (self.__sequence + other) def __sub__ (self, other): if isinstance (other, Term): return self.__sequence - other.__sequence else: return self + -other
[docs] def year (self): return self.__sequence // 3
[docs] def month (self): return self.__sequence % 3 * 4 + 1
[docs] def seasonName (self): return seasons[self.month ()]
[docs] def seasonInitial (self): return seasons[self.month ()][0]
[docs] def description (self): return "%s %04d" % (self.seasonName (), self.year ())
[docs] def abbreviation (self): return "%s%02d" % (self.seasonInitial (), self.year () % 100)
[docs] def code (self): return "%04d" % self.numericCode ()
[docs] def numericCode (self): return (self.year () - 1900) * 10 + self.month ()
[docs] def oldCode (self): return "%02d%02d" % (self.year () % 100, self.month ())
[docs] def nextTerm (self): return self + 1
[docs] def prevTerm (self): return self - 1
[docs] def nextYear (self): return self + 3
[docs] def prevYear (self): return self - 3
[docs] def countFrom (self, by=1): while True: yield self self += by
[docs] def startDate (self): return datetime.date (self.year (), self.month (), 1)
[docs] def render_date_selector (self, name, current=None): return render_date_selector_2 (name, current, self.startDate (), 4)
[docs] def render_time_selector (self, name, start, hours, current=None): return [ self.render_date_selector ('%sd' % name, None if current is None else current.date ()), ' at ', render_time_selector_2 ('%st' % name, start, hours, None if current is None else current.time ()) ]
[docs]def make (year, month): if not month in (1, 5, 9): raise ValueError ("invalid month for UW term: %d" % month) return Term (year * 3 + (month - 1) // 4)
[docs]def current (): return fromDate (datetime.date.today ())
[docs]def fromDate (date): return make (date.year, (date.month - 1) // 4 * 4 + 1)
[docs]def fromCode (code): if code is None: return None code = int (code) return make (code // 10 + 1900, code % 10)
[docs]def render_term_select (name, terms, term=None, blank=False, class_=None): if term is not None: term = term.code () return render_select (name, ((term.code (), term.description ()) for term in terms), value=term, blank=blank, class_=class_)
[docs]def fromOldCode (code): """Convert an old term code into a term object. Years from 50-99 are assuming to be in the 1900s while 00-49 are 2000s. This allows all old term codes from just before the founding of the University up to Fall 2049 to be processed correctly. If we're still using the old codes for anything in Fall 2049 then I'm not responsible for the consequences. """ code = int (code) year = code // 100 if year >= 50: year += 1900 else: year += 2000 return make (year, code % 100)