terom@50: """ terom@50: Some additional helpers terom@50: """ terom@50: terom@113: import datetime terom@113: import calendar as _calendar terom@60: terom@54: import qmsk.web.helpers terom@50: terom@73: import preferences, urls, config terom@54: terom@54: class Helpers (qmsk.web.helpers.Helpers) : terom@50: """ terom@54: Our set of helpers, inheriting from base helpers terom@50: """ terom@50: terom@112: # set contructor... terom@112: set = set terom@112: terom@112: # reference to calendar instance terom@113: calendar = _calendar.Calendar() terom@113: terom@113: # list of (month_num, month_name) for the months in the year terom@113: months = list(enumerate(_calendar.month_name))[1:] terom@112: terom@54: def tz_name (self, tz) : terom@54: """ terom@54: Returns a string describing the given timezone terom@54: """ terom@50: terom@73: return self.now().strftime(config.TIMEZONE_FMT) terom@50: terom@54: def fmt_month (self, date) : terom@54: """ terom@54: Formats a month terom@54: """ terom@54: terom@73: return date.strftime(config.MONTH_FMT) terom@54: terom@54: def fmt_weekday (self, wday) : terom@54: """ terom@54: Formats an abbreviated weekday name terom@54: """ terom@54: terom@113: return _calendar.day_abbr[wday] terom@54: terom@54: def build_date (self, month, mday) : terom@54: """ terom@54: Returns a datetime.date for the given (month.year, month.month, mday) terom@54: """ terom@54: terom@54: return datetime.date(month.year, month.month, mday) terom@58: terom@58: def now (self) : terom@58: """ terom@58: Build current time terom@58: """ terom@58: terom@62: return self.ctx['prefs'][preferences.timezone].localize(datetime.datetime.now()) terom@58: terom@58: def today (self) : terom@58: """ terom@58: Build today's date terom@58: """ terom@58: terom@58: return self.now().date() terom@54: terom@54: def is_today (self, date) : terom@54: """ terom@58: Checks if the given date is today terom@54: """ terom@54: terom@54: # construct current date terom@58: return date == self.today() terom@55: terom@58: def is_this_month (self, month) : terom@58: """ terom@58: Checks the given month is the current month terom@58: """ terom@58: terom@58: today = self.today() terom@58: terom@58: return (month.year == today.year and month.month == today.month) terom@58: terom@112: @staticmethod terom@112: def _wrap_year (year, month) : terom@55: """ terom@112: Wraps month to between [1, 12], spilling overflow/underflow by to year. terom@55: terom@112: Returns (year, month) terom@112: """ terom@112: terom@112: # underflow? terom@112: if month == 0 : terom@112: # wrap to previous year terom@112: return (year - 1, 12) terom@112: terom@112: # overflow? terom@112: elif month == 13 : terom@112: # wrap to next year terom@112: return (year + 1, 1) terom@112: terom@112: # sane value terom@112: elif 1 <= month <= 12 : terom@112: return (year, month) terom@112: terom@112: # insane value terom@55: else : terom@112: assert False, "invalid year/month: %d/%d" % (year, month) terom@55: terom@55: def prev_month (self, month) : terom@55: """ terom@112: Returns the month preceding the given one (as a datetime.datetime) terom@55: """ terom@112: terom@112: # previous month terom@112: y, m = self._wrap_year(month.year, month.month - 1) terom@112: terom@112: # build datetime terom@112: return datetime.datetime(year=y, month=m, day=1, tzinfo=month.tzinfo) terom@55: terom@55: def next_month (self, month) : terom@55: """ terom@112: Returns the month following the given one (as a datetime.datetime) terom@55: """ terom@112: terom@112: # previous month terom@112: y, m = self._wrap_year(month.year, month.month + 1) terom@112: terom@112: # build datetime terom@112: return datetime.datetime(year=y, month=m, day=1, tzinfo=month.tzinfo) terom@60: terom@60: def fmt_time (self, time=None) : terom@60: """ terom@60: Format given time, or current time terom@60: """ terom@60: terom@60: # defaults terom@60: if not time : terom@60: time = self.now() terom@55: terom@60: return time.strftime(self.ctx['prefs'][preferences.time_format]) terom@60: terom@60: def fmt_date (self, date=None) : terom@60: """ terom@60: Format given date, or current date terom@60: """ terom@60: terom@60: # defaults terom@60: if not date : terom@60: date = self.now() terom@60: terom@60: return date.strftime(self.ctx['prefs'][preferences.date_format]) terom@60: terom@63: def build_url (self, url, **params) : terom@63: """ terom@63: Build URL with our request object terom@63: """ terom@63: terom@63: return url.build(self.ctx['req'], **params) terom@72: terom@72: def utc_timestamp (self, dtz) : terom@72: """ terom@72: Build an UTC timestamp from the given datetime terom@72: """ terom@63: terom@72: return urls.types['ts'].build(dtz) terom@73: terom@73: def skip_next (self, count, skip) : terom@73: """ terom@73: Return skip offset for next page terom@73: """ terom@72: terom@73: return count + skip terom@73: terom@73: def skip_page (self, count, page) : terom@73: """ terom@73: Skip to page terom@73: """ terom@73: terom@73: if page : terom@73: return count * page terom@73: terom@73: else : terom@73: return None terom@73: terom@73: def skip_prev (self, count, skip) : terom@73: """ terom@73: Return skip offset for previous page, None for first page terom@73: """ terom@73: terom@73: if skip > count : terom@73: return skip - count terom@73: terom@73: else : terom@73: return None terom@73: terom@73: def max (self, *values) : terom@73: """ terom@73: Returns the largest of the given values terom@73: """ terom@73: terom@73: return max(values) terom@79: terom@113: def select_options (self, key_values, selected_key=None) : terom@79: """ terom@113: Render a series of