helpers.py
author Tero Marttila <terom@fixme.fi>
Thu, 12 Feb 2009 00:16:52 +0200
changeset 115 751e3fcd11d2
parent 114 d4848d807fd1
child 131 67f5d2fdca1d
permissions -rw-r--r--
have dates in URLs be partial timestamps - fix datetime-timezone-comparison mess
"""
    Some additional helpers
"""

import datetime
import calendar as _calendar

import qmsk.web.helpers

import preferences, urls, config

class Helpers (qmsk.web.helpers.Helpers) :
    """
        Our set of helpers, inheriting from base helpers
    """

    # set contructor...
    set = set

    # reference to calendar instance
    calendar = _calendar.Calendar()

    # list of (month_num, month_name) for the months in the year
    months = list(enumerate(_calendar.month_name))[1:]

    def tz_name (self, tz) :
        """
            Returns a string describing the given timezone
        """

        return self.now().strftime(config.TIMEZONE_FMT)

    def fmt_month (self, date) :
        """
            Formats a month
        """

        return date.strftime(config.MONTH_FMT)
        
    def fmt_weekday (self, wday) :
        """
            Formats an abbreviated weekday name
        """

        return _calendar.day_abbr[wday]

    def build_date (self, month, mday) :
        """
            Returns a datetime.datetime for the given (month.year, month.month, mday)
        """

        return self.ctx['prefs'][preferences.timezone].localize(datetime.datetime(month.year, month.month, mday))
    
    def now (self) :
        """
            Build current time
        """

        return self.ctx['prefs'][preferences.timezone].localize(datetime.datetime.now())

    def today (self) :
        """
            Build today's date
        """
        
        return self.now().date()

    def is_today (self, dt) :
        """
            Checks if the given datetime.datetime is today
        """

        # compare with current date
        return dt.date() == self.today()
    
    def is_this_month (self, month) :
        """
            Checks the given month is the current month
        """

        today = self.today()

        return (month.year == today.year and month.month == today.month)

    @staticmethod
    def _wrap_year (year, month) :
        """
            Wraps month to between [1, 12], spilling overflow/underflow by to year.

            Returns (year, month)
        """
        
        # underflow?
        if month == 0 :
            # wrap to previous year
            return (year - 1, 12)
        
        # overflow?
        elif month == 13 :
            # wrap to next year
            return (year + 1, 1)
        
        # sane value
        elif 1 <= month <= 12 :
            return (year, month)
        
        # insane value
        else :
            assert False, "invalid year/month: %d/%d" % (year, month)

    def prev_month (self, month) :
        """
            Returns the month preceding the given one (as a datetime.datetime)
        """
        
        # previous month
        y, m = self._wrap_year(month.year, month.month - 1)
        
        # build datetime
        return datetime.datetime(year=y, month=m, day=1, tzinfo=month.tzinfo)

    def next_month (self, month) :
        """
            Returns the month following the given one (as a datetime.datetime)
        """
        
        # previous month
        y, m = self._wrap_year(month.year, month.month + 1)
        
        # build datetime
        return datetime.datetime(year=y, month=m, day=1, tzinfo=month.tzinfo)
    
    def fmt_time (self, time=None) :
        """
            Format given time, or current time
        """
        
        # defaults
        if not time :
            time = self.now()

        return time.strftime(self.ctx['prefs'][preferences.time_format])

    def fmt_date (self, date=None) :
        """
            Format given date, or current date
        """
        
        # defaults
        if not date :
            date = self.now()

        return date.strftime(self.ctx['prefs'][preferences.date_format])

    def url (self, url, **params) :
        """
            Build URL with our request object
        """

        return url.build(self.ctx['req'], **params)

    # old name
    build_url = url

    def utc_timestamp (self, dtz) :
        """
            Build an UTC timestamp from the given datetime
        """

        return urls.types['ts'].build(dtz)
    
    def skip_next (self, count, skip) :
        """
            Return skip offset for next page
        """

        return count + skip
    
    def skip_page (self, count, page) :
        """
            Skip to page
        """

        if page :
            return count * page

        else :
            return None

    def skip_prev (self, count, skip) :
        """
            Return skip offset for previous page, None for first page
        """

        if skip > count :
            return skip - count

        else :
            return None

    def max (self, *values) :
        """
            Returns the largest of the given values
        """

        return max(values)
    
    def select_options (self, key_values, selected_key=None) :
        """
            Render a series of <option> tags for <select>.

            The given key_values is an iterable of (key, value) pairs, key may be None if it's the same as value.
        """

        return '\n'.join(
            '\t<option%s%s>%s</option>' % (
                ' value="%s"' % key if key is not None else '',
                ' selected="selected"' if (key if key is not None else value) == selected_key else '',
                value
            ) for key, value in key_values
        )
    
    def prev_date (self, date) :
        """
            Returns the previous date for the given datetime-date
        """

        return datetime.datetime(date.year, date.month, date.day, tzinfo=date.tzinfo) - datetime.timedelta(days=1)

    def next_date (self, date) :
        """
            Returns the previous date for the given datetime-date
        """

        return datetime.datetime(date.year, date.month, date.day, tzinfo=date.tzinfo) + datetime.timedelta(days=1)