terom@50: """ terom@50: Miscellaneous things terom@50: """ terom@50: terom@72: import datetime, calendar, pytz terom@95: import os, errno terom@50: terom@51: from qmsk.web.urltree import URLType terom@51: terom@51: class URLChannelName (URLType) : terom@50: """ terom@51: Handle LogChannel names in URLs. Deals with instances of LogChannel terom@50: """ terom@50: terom@51: def __init__ (self, channels) : terom@50: """ terom@51: Use the given { name -> LogChannel } dict terom@51: """ terom@51: terom@51: self.channels = channels terom@51: terom@51: def parse (self, chan_name) : terom@51: """ terom@51: chan_name -> LogChannel terom@51: """ terom@51: terom@51: return self.channels[chan_name] terom@51: terom@51: def build (self, chan) : terom@51: """ terom@51: LogChannel -> chan_name terom@51: """ terom@51: terom@51: return chan.id terom@51: terom@51: class URLDateType (URLType) : terom@51: """ terom@117: Handle dates in URLs as naive datetime objects (with indeterminate time info) terom@51: """ terom@51: terom@73: def __init__ (self, date_fmt) : terom@51: """ terom@51: Format/parse dates using the given format terom@51: """ terom@51: terom@51: self.date_fmt = date_fmt terom@51: terom@117: def parse (self, date_str) : terom@51: """ terom@117: date_str -> naive datetime.datetime terom@50: """ terom@50: terom@117: return datetime.datetime.strptime(date_str, self.date_fmt) terom@50: terom@117: def build (self, date) : terom@51: """ terom@117: datetime.date -> date_str terom@51: """ terom@50: terom@117: return date.strftime(self.date_fmt) terom@50: terom@72: class URLTimestampType (URLType) : terom@72: """ terom@72: Handles an integer UNIX timestamp as an UTC datetime terom@72: """ terom@72: terom@72: def parse (self, timestamp_str) : terom@72: """ terom@72: timestamp_str -> pytz.utc datetime.datetime terom@72: """ terom@89: terom@89: return from_utc_timestamp(int(timestamp_str)) terom@72: terom@72: def build (self, dtz) : terom@72: """ terom@72: pytz.utc datetime.datetime -> timestamp_str terom@72: """ terom@89: terom@89: return str(to_utc_timestamp(dtz)) terom@72: terom@89: def from_utc_timestamp (timestamp) : terom@89: """ terom@89: Converts a UNIX timestamp into a datetime.datetime terom@89: """ terom@72: terom@89: return datetime.datetime.utcfromtimestamp(timestamp).replace(tzinfo=pytz.utc) terom@89: terom@89: def to_utc_timestamp (dt) : terom@89: """ terom@89: Converts a datetime.datetime into a UNIX timestamp terom@89: """ terom@89: terom@89: return calendar.timegm(dt.utctimetuple()) terom@89: terom@95: def mtime (path, ignore_missing=False) : terom@95: """ terom@95: Gets the mtime for the given path as an UTC datetime, or None, if the file doesn't exist and ignore_missing terom@95: """ terom@95: terom@95: try : terom@95: # stat terom@95: st = os.stat(path) terom@95: terom@95: # trap IOError terom@95: except os.error, e : terom@95: # ENOENT? terom@95: if ignore_missing and e.errno == errno.ENOENT : terom@95: return None terom@95: terom@95: else : terom@95: raise terom@95: terom@95: else : terom@95: # decode terom@95: return from_utc_timestamp(st.st_mtime) terom@95: terom@129: class FixedOffsetTimezone (pytz._FixedOffset) : terom@129: """ terom@129: A Fixed-offset timezone with no DST info, compatible with pytz. terom@129: terom@129: This is based on pytz._FixedOffset, but overrides dst() to return timedelta(0) terom@129: """ terom@129: terom@129: def __init__ (self, minutes) : terom@129: """ terom@129: Minutes is simply the offset from UTC in minutes, positive or negative, at most 24h. terom@129: """ terom@129: terom@129: pytz._FixedOffset.__init__(self, minutes) terom@129: terom@129: def dst (self, dt) : terom@129: """ terom@129: No DST info terom@129: """ terom@129: terom@129: return datetime.timedelta(0) terom@129: