Django

Code

Changeset 969

Show
Ignore:
Timestamp:
10/20/05 00:30:11 (3 years ago)
Author:
adrian
Message:

Lightly refactored django.utils.dateformat to make it use less code. Also integrated some of Sune's improvements from the #479 patch, including support for backslash escaping. Also vastly improved template docs for the {% now %} tag

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/utils/dateformat.py

    r313 r969  
    1212""" 
    1313 
     14from django.utils.dates import MONTHS, MONTHS_AP, WEEKDAYS 
    1415from calendar import isleap 
    15 from dates import MONTHS, MONTHS_AP, WEEKDAYS 
    16  
    17 class DateFormat: 
    18     year_days = [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334] 
    19  
    20     def __init__(self, d): 
    21         self.date = d 
     16import re 
     17 
     18re_formatchars = re.compile(r'(?<!\\)([aABdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])') 
     19re_escaped = re.compile(r'\\(.)') 
     20 
     21class Formatter: 
     22    def format(self, formatstr): 
     23        pieces = [] 
     24        for i, piece in enumerate(re_formatchars.split(formatstr)): 
     25            if i % 2: 
     26                pieces.append(str(getattr(self, piece)())) 
     27            elif piece: 
     28                pieces.append(re_escaped.sub(r'\1', piece)) 
     29        return ''.join(pieces) 
     30 
     31class TimeFormat(Formatter): 
     32    def __init__(self, t): 
     33        self.data = t 
    2234 
    2335    def a(self): 
    2436        "'a.m.' or 'p.m.'" 
    25         if self.date.hour > 11: 
     37        if self.data.hour > 11: 
    2638            return 'p.m.' 
    2739        return 'a.m.' 
     
    2941    def A(self): 
    3042        "'AM' or 'PM'" 
    31         if self.date.hour > 11: 
    32             return 'PM' 
    33         return 'AM' 
     43        return self.a().upper() 
    3444 
    3545    def B(self): 
    3646        "Swatch Internet time" 
    3747        raise NotImplementedError 
    38  
    39     def d(self): 
    40         "Day of the month, 2 digits with leading zeros; i.e. '01' to '31'" 
    41         return '%02d' % self.date.day 
    42  
    43     def D(self): 
    44         "Day of the week, textual, 3 letters; e.g. 'Fri'" 
    45         return WEEKDAYS[self.date.weekday()][0:3] 
    4648 
    4749    def f(self): 
     
    5153        Proprietary extension. 
    5254        """ 
    53         if self.date.minute == 0: 
     55        if self.data.minute == 0: 
    5456            return self.g() 
    5557        return '%s:%s' % (self.g(), self.i()) 
    5658 
    57     def F(self): 
    58         "Month, textual, long; e.g. 'January'" 
    59         return MONTHS[self.date.month] 
    60  
    6159    def g(self): 
    6260        "Hour, 12-hour format without leading zeros; i.e. '1' to '12'" 
    63         if self.date.hour == 0: 
     61        if self.data.hour == 0: 
    6462            return 12 
    65         if self.date.hour > 12: 
    66             return self.date.hour - 12 
    67         return self.date.hour 
     63        if self.data.hour > 12: 
     64            return self.data.hour - 12 
     65        return self.data.hour 
    6866 
    6967    def G(self): 
    7068        "Hour, 24-hour format without leading zeros; i.e. '0' to '23'" 
    71         return self.date.hour 
     69        return self.data.hour 
    7270 
    7371    def h(self): 
     
    8179    def i(self): 
    8280        "Minutes; i.e. '00' to '59'" 
    83         return '%02d' % self.date.minute 
    84  
    85     def I(self): 
    86         "'1' if Daylight Savings Time, '0' otherwise." 
    87         raise NotImplementedError 
    88  
    89     def j(self): 
    90         "Day of the month without leading zeros; i.e. '1' to '31'" 
    91         return self.date.day 
    92  
    93     def l(self): 
    94         "Day of the week, textual, long; e.g. 'Friday'" 
    95         return WEEKDAYS[self.date.weekday()] 
    96  
    97     def L(self): 
    98         "Boolean for whether it is a leap year; i.e. True or False" 
    99         return isleap(self.date.year) 
    100  
    101     def m(self): 
    102         "Month; i.e. '01' to '12'" 
    103         return '%02d' % self.date.month 
    104  
    105     def M(self): 
    106         "Month, textual, 3 letters; e.g. 'Jan'" 
    107         return MONTHS[self.date.month][0:3] 
    108  
    109     def n(self): 
    110         "Month without leading zeros; i.e. '1' to '12'" 
    111         return self.date.month 
    112  
    113     def N(self): 
    114         "Month abbreviation in Associated Press style. Proprietary extension." 
    115         return MONTHS_AP[self.date.month] 
    116  
    117     def O(self): 
    118         "Difference to Greenwich time in hours; e.g. '+0200'" 
    119         raise NotImplementedError 
     81        return '%02d' % self.data.minute 
    12082 
    12183    def P(self): 
     
    12688        Proprietary extension. 
    12789        """ 
    128         if self.date.minute == 0 and self.date.hour == 0: 
     90        if self.data.minute == 0 and self.data.hour == 0: 
    12991            return 'midnight' 
    130         if self.date.minute == 0 and self.date.hour == 12: 
     92        if self.data.minute == 0 and self.data.hour == 12: 
    13193            return 'noon' 
    13294        return '%s %s' % (self.f(), self.a()) 
    13395 
     96    def s(self): 
     97        "Seconds; i.e. '00' to '59'" 
     98        return '%02d' % self.data.second 
     99 
     100class DateFormat(Formatter): 
     101    year_days = [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334] 
     102 
     103    def __init__(self, d): 
     104        self.data = d 
     105 
     106    def d(self): 
     107        "Day of the month, 2 digits with leading zeros; i.e. '01' to '31'" 
     108        return '%02d' % self.data.day 
     109 
     110    def D(self): 
     111        "Day of the week, textual, 3 letters; e.g. 'Fri'" 
     112        return WEEKDAYS[self.data.weekday()][0:3] 
     113 
     114    def F(self): 
     115        "Month, textual, long; e.g. 'January'" 
     116        return MONTHS[self.data.month] 
     117 
     118    def I(self): 
     119        "'1' if Daylight Savings Time, '0' otherwise." 
     120        raise NotImplementedError 
     121 
     122    def j(self): 
     123        "Day of the month without leading zeros; i.e. '1' to '31'" 
     124        return self.data.day 
     125 
     126    def l(self): 
     127        "Day of the week, textual, long; e.g. 'Friday'" 
     128        return WEEKDAYS[self.data.weekday()] 
     129 
     130    def L(self): 
     131        "Boolean for whether it is a leap year; i.e. True or False" 
     132        return isleap(self.data.year) 
     133 
     134    def m(self): 
     135        "Month; i.e. '01' to '12'" 
     136        return '%02d' % self.data.month 
     137 
     138    def M(self): 
     139        "Month, textual, 3 letters; e.g. 'Jan'" 
     140        return MONTHS[self.data.month][0:3] 
     141 
     142    def n(self): 
     143        "Month without leading zeros; i.e. '1' to '12'" 
     144        return self.data.month 
     145 
     146    def N(self): 
     147        "Month abbreviation in Associated Press style. Proprietary extension." 
     148        return MONTHS_AP[self.data.month] 
     149 
     150    def O(self): 
     151        "Difference to Greenwich time in hours; e.g. '+0200'" 
     152        raise NotImplementedError 
     153 
    134154    def r(self): 
    135155        "RFC 822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'" 
    136156        raise NotImplementedError 
    137157 
    138     def s(self): 
    139         "Seconds; i.e. '00' to '59'" 
    140         return '%02d' % self.date.second 
    141  
    142158    def S(self): 
    143159        "English ordinal suffix for the day of the month, 2 characters; i.e. 'st', 'nd', 'rd' or 'th'" 
    144         if self.date.day in (11, 12, 13): # Special case 
     160        if self.data.day in (11, 12, 13): # Special case 
    145161            return 'th' 
    146         last = self.date.day % 10 
     162        last = self.data.day % 10 
    147163        if last == 1: 
    148164            return 'st' 
     
    167183    def w(self): 
    168184        "Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)" 
    169         weekday = self.date.weekday() 
    170         if weekday == 0: 
    171             return 6 
    172         return weekday - 1 
     185        return (self.data.weekday() + 1) % 7 
    173186 
    174187    def W(self): 
     
    176189        # Algorithm from http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt 
    177190        week_number = None 
    178         jan1_weekday = self.date.replace(month=1, day=1).weekday() + 1 
    179         weekday = self.date.weekday() + 1 
     191        jan1_weekday = self.data.replace(month=1, day=1).weekday() + 1 
     192        weekday = self.data.weekday() + 1 
    180193        day_of_year = self.z() 
    181194        if day_of_year <= (8 - jan1_weekday) and jan1_weekday > 4: 
    182             if jan1_weekday == 5 or (jan1_weekday == 6 and isleap(self.date.year-1)): 
     195            if jan1_weekday == 5 or (jan1_weekday == 6 and isleap(self.data.year-1)): 
    183196                week_number = 53 
    184197            else: 
    185198                week_number = 52 
    186199        else: 
    187             if isleap(self.date.year): 
     200            if isleap(self.data.year): 
    188201                i = 366 
    189202            else: 
     
    198211        return week_number 
    199212 
     213    def y(self): 
     214        "Year, 2 digits; e.g. '99'" 
     215        return str(self.data.year)[2:] 
     216 
    200217    def Y(self): 
    201218        "Year, 4 digits; e.g. '1999'" 
    202         return self.date.year 
    203  
    204     def y(self): 
    205         "Year, 2 digits; e.g. '99'" 
    206         return str(self.date.year)[2:] 
     219        return self.data.year 
    207220 
    208221    def z(self): 
    209222        "Day of the year; i.e. '0' to '365'" 
    210         doy = self.year_days[self.date.month] + self.date.day 
    211         if self.L() and self.date.month > 2: 
     223        doy = self.year_days[self.data.month] + self.data.day 
     224        if self.L() and self.data.month > 2: 
    212225            doy += 1 
    213226        return doy 
     
    219232        raise NotImplementedError 
    220233 
    221     def format(self, formatstr): 
    222         result = '' 
    223         for char in formatstr: 
    224             try: 
    225                 result += str(getattr(self, char)()) 
    226             except AttributeError: 
    227                 result += char 
    228         return result 
    229  
    230 class TimeFormat: 
    231     def __init__(self, t): 
    232         self.time = t 
    233  
    234     def a(self): 
    235         "'a.m.' or 'p.m.'" 
    236         if self.time.hour > 11: 
    237             return 'p.m.' 
    238         else: 
    239             return 'a.m.' 
    240  
    241     def A(self): 
    242         "'AM' or 'PM'" 
    243         return self.a().upper() 
    244  
    245     def B(self): 
    246         "Swatch Internet time" 
    247         raise NotImplementedError 
    248  
    249     def f(self): 
    250         """ 
    251         Time, in 12-hour hours and minutes, with minutes left off if they're zero. 
    252         Examples: '1', '1:30', '2:05', '2' 
    253         Proprietary extension. 
    254         """ 
    255         if self.time.minute == 0: 
    256             return self.g() 
    257         return '%s:%s' % (self.g(), self.i()) 
    258  
    259     def g(self): 
    260         "Hour, 12-hour format without leading zeros; i.e. '1' to '12'" 
    261         if self.time.hour == 0: 
    262             return 12 
    263         if self.time.hour > 12: 
    264             return self.time.hour - 12 
    265         return self.time.hour 
    266  
    267     def G(self): 
    268         "Hour, 24-hour format without leading zeros; i.e. '0' to '23'" 
    269         return self.time.hour 
    270  
    271     def h(self): 
    272         "Hour, 12-hour format; i.e. '01' to '12'" 
    273         return '%02d' % self.g() 
    274  
    275     def H(self): 
    276         "Hour, 24-hour format; i.e. '00' to '23'" 
    277         return '%02d' % self.G() 
    278  
    279     def i(self): 
    280         "Minutes; i.e. '00' to '59'" 
    281         return '%02d' % self.time.minute 
    282  
    283     def P(self): 
    284         """ 
    285         Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off 
    286         if they're zero and the strings 'midnight' and 'noon' if appropriate. 
    287         Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.' 
    288         Proprietary extension. 
    289         """ 
    290         if self.time.minute == 0 and self.time.hour == 0: 
    291             return 'midnight' 
    292         if self.time.minute == 0 and self.time.hour == 12: 
    293             return 'noon' 
    294         return '%s %s' % (self.f(), self.a()) 
    295  
    296     def s(self): 
    297         "Seconds; i.e. '00' to '59'" 
    298         return '%02d' % self.time.second 
    299  
    300     def format(self, formatstr): 
    301         result = '' 
    302         for char in formatstr: 
    303             try: 
    304                 result += str(getattr(self, char)()) 
    305             except AttributeError: 
    306                 result += char 
    307         return result 
    308  
    309234def format(value, format_string): 
    310235    "Convenience function" 
  • django/trunk/docs/templates.txt

    r911 r969  
    447447        <h1>Archive for {{ year }}</h1> 
    448448 
    449         {% for date in days %} 
    450         {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %} 
    451         <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a> 
     449        {% for day in days %} 
     450        {% ifchanged %}<h3>{{ day|date:"F" }}</h3>{% endifchanged %} 
     451        <a href="{{ day|date:"M/d"|lower }}/">{{ day|date:"j" }}</a> 
    452452        {% endfor %} 
    453453 
     
    480480    Display the date, formatted according to the given string. 
    481481 
    482     Uses the same format as PHP's ``date()`` function; see http://php.net/date 
    483     for all the possible values. 
    484  
    485     Sample usage:: 
     482    Uses the same format as PHP's ``date()`` function (http://php.net/date) 
     483    with some custom extensions. 
     484 
     485    Available format strings: 
     486 
     487    ================  ======================================  ===================== 
     488    Format character  Description                             Example output 
     489    ================  ======================================  ===================== 
     490    a                 ``'a.m.'`` or ``'p.m.'`` (Note that     ``'a.m.'`` 
     491                      this is slightly different than PHP's 
     492                      output, because this includes periods 
     493                      to match Associated Press style.) 
     494    A                 ``'AM'`` or ``'PM'``.                   ``'AM'`` 
     495    B                 Not implemented. 
     496    d                 Day of the month, 2 digits with         ``'01'`` to ``'31'`` 
     497                      leading zeros. 
     498    D                 Day of the week, textual, 3 letters.    ``'Fri'`` 
     499    f                 Time, in 12-hour hours and minutes,     ``'1'``, ``'1:30'`` 
     500                      with minutes left off if they're zero. 
     501                      Proprietary extension. 
     502    F                 Month, textual, long.                   ``'January'`` 
     503    g                 Hour, 12-hour format without leading    ``'1'`` to ``'12'`` 
     504                      zeros. 
     505    G                 Hour, 24-hour format without leading    ``'0'`` to ``'23'`` 
     506                      zeros. 
     507    h                 Hour, 12-hour format.                   ``'01'`` to ``'12'`` 
     508    H                 Hour, 24-hour format.                   ``'00'`` to ``'23'`` 
     509    i                 Minutes.                                ``'00'`` to ``'59'`` 
     510    I                 Not implemented. 
     511    j                 Day of the month without leading zeros. ``'1'`` to ``'31'`` 
     512    l                 Day of the week, textual, long.         ``'Friday'`` 
     513    L                 Boolean for whether it's a leap year.   ``True`` or ``False`` 
     514    m                 Month, 2 digits with leading zeros.     ``'01'`` to ``'12'`` 
     515    M                 Month, textual, 3 letters.              ``'Jan'`` 
     516    n                 Month without leading zeros.            ``'1'`` to ``'12'`` 
     517    N                 Month abbreviation in Associated Press  ``'Jan.'``, ``'Feb.'``, ``'March'``, ``'May'`` 
     518                      style. Proprietary extension. 
     519    O                 Not implemented. 
     520    P                 Time, in 12-hour hours, minutes and     ``'1 a.m.'``, ``'1:30 p.m.'``, ``'midnight'``, ``'noon'``, ``'12:30 p.m.'`` 
     521                      'a.m.'/'p.m.', with minutes left off 
     522                      if they're zero and the special-case 
     523                      strings 'midnight' and 'noon' if 
     524                      appropriate. Proprietary extension. 
     525    r                 Not implemented. 
     526    s                 Seconds, 2 digits with leading zeros.   ``'00'`` to ``'59'`` 
     527    S                 English ordinal suffix for day of the   ``'st'``, ``'nd'``, ``'rd'`` or ``'th'`` 
     528                      month, 2 characters. 
     529    t                 Not implemented. 
     530    T                 Not implemented. 
     531    U                 Not implemented. 
     532    w                 Day of the week, digits without         ``'0'`` (Sunday) to ``'6'`` (Saturday) 
     533                      leading zeros. 
     534    W                 ISO-8601 week number of year, with      ``1``, ``23`` 
     535                      weeks starting on Monday. 
     536    y                 Year, 2 digits.                         ``'99'`` 
     537    Y                 Year, 4 digits.                         ``'1999'`` 
     538    z                 Day of the year.                        ``0`` to ``365`` 
     539    Z                 Not implemented. 
     540 
     541    Example:: 
    486542 
    487543        It is {% now "jS F Y H:i" %} 
     544 
     545    Note that you can backslash-escape a format string if you want to use the 
     546    "raw" value. In this example, "f" is backslash-escaped, because otherwise 
     547    "f" is a format string that displays the time. The "o" doesn't need to be 
     548    escaped, because it's not a format character.:: 
     549 
     550        It is the {% "jS o\f F" %} 
     551 
     552    (Displays "It is the 4th of September" %} 
    488553 
    489554``regroup``