~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to django/utils/dateformat.py

  • Committer: Package Import Robot
  • Author(s): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
import datetime
19
19
 
20
20
from django.utils.dates import MONTHS, MONTHS_3, MONTHS_ALT, MONTHS_AP, WEEKDAYS, WEEKDAYS_ABBR
21
 
from django.utils.tzinfo import LocalTimezone
22
21
from django.utils.translation import ugettext as _
23
22
from django.utils.encoding import force_text
24
23
from django.utils import six
25
 
from django.utils.timezone import is_aware, is_naive
 
24
from django.utils.timezone import get_default_timezone, is_aware, is_naive
26
25
 
27
26
re_formatchars = re.compile(r'(?<!\\)([aAbBcdDeEfFgGhHiIjlLmMnNoOPrsStTUuwWyYzZ])')
28
27
re_escaped = re.compile(r'\\(.)')
29
28
 
 
29
 
30
30
class Formatter(object):
31
31
    def format(self, formatstr):
32
32
        pieces = []
37
37
                pieces.append(re_escaped.sub(r'\1', piece))
38
38
        return ''.join(pieces)
39
39
 
 
40
 
40
41
class TimeFormat(Formatter):
41
 
    def __init__(self, t):
42
 
        self.data = t
 
42
 
 
43
    def __init__(self, obj):
 
44
        self.data = obj
 
45
        self.timezone = None
 
46
 
 
47
        # We only support timezone when formatting datetime objects,
 
48
        # not date objects (timezone information not appropriate),
 
49
        # or time objects (against established django policy).
 
50
        if isinstance(obj, datetime.datetime):
 
51
            if is_naive(obj):
 
52
                self.timezone = get_default_timezone()
 
53
            else:
 
54
                self.timezone = obj.tzinfo
43
55
 
44
56
    def a(self):
45
57
        "'a.m.' or 'p.m.'"
55
67
 
56
68
    def B(self):
57
69
        "Swatch Internet time"
58
 
        raise NotImplementedError
 
70
        raise NotImplementedError('may be implemented in a future release')
 
71
 
 
72
    def e(self):
 
73
        """
 
74
        Timezone name.
 
75
 
 
76
        If timezone information is not available, this method returns
 
77
        an empty string.
 
78
        """
 
79
        if not self.timezone:
 
80
            return ""
 
81
 
 
82
        try:
 
83
            if hasattr(self.data, 'tzinfo') and self.data.tzinfo:
 
84
                # Have to use tzinfo.tzname and not datetime.tzname
 
85
                # because datatime.tzname does not expect Unicode
 
86
                return self.data.tzinfo.tzname(self.data) or ""
 
87
        except NotImplementedError:
 
88
            pass
 
89
        return ""
59
90
 
60
91
    def f(self):
61
92
        """
92
123
        "Minutes; i.e. '00' to '59'"
93
124
        return '%02d' % self.data.minute
94
125
 
 
126
    def O(self):
 
127
        """
 
128
        Difference to Greenwich time in hours; e.g. '+0200', '-0430'.
 
129
 
 
130
        If timezone information is not available, this method returns
 
131
        an empty string.
 
132
        """
 
133
        if not self.timezone:
 
134
            return ""
 
135
 
 
136
        seconds = self.Z()
 
137
        sign = '-' if seconds < 0 else '+'
 
138
        seconds = abs(seconds)
 
139
        return "%s%02d%02d" % (sign, seconds // 3600, (seconds // 60) % 60)
 
140
 
95
141
    def P(self):
96
142
        """
97
143
        Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off
109
155
        "Seconds; i.e. '00' to '59'"
110
156
        return '%02d' % self.data.second
111
157
 
 
158
    def T(self):
 
159
        """
 
160
        Time zone of this machine; e.g. 'EST' or 'MDT'.
 
161
 
 
162
        If timezone information is not available, this method returns
 
163
        an empty string.
 
164
        """
 
165
        if not self.timezone:
 
166
            return ""
 
167
 
 
168
        name = self.timezone.tzname(self.data) if self.timezone else None
 
169
        if name is None:
 
170
            name = self.format('O')
 
171
        return six.text_type(name)
 
172
 
112
173
    def u(self):
113
174
        "Microseconds; i.e. '000000' to '999999'"
114
 
        return '%06d' %self.data.microsecond
 
175
        return '%06d' % self.data.microsecond
 
176
 
 
177
    def Z(self):
 
178
        """
 
179
        Time zone offset in seconds (i.e. '-43200' to '43200'). The offset for
 
180
        timezones west of UTC is always negative, and for those east of UTC is
 
181
        always positive.
 
182
 
 
183
        If timezone information is not available, this method returns
 
184
        an empty string.
 
185
        """
 
186
        if not self.timezone:
 
187
            return ""
 
188
 
 
189
        offset = self.timezone.utcoffset(self.data)
 
190
        # `offset` is a datetime.timedelta. For negative values (to the west of
 
191
        # UTC) only days can be negative (days=-1) and seconds are always
 
192
        # positive. e.g. UTC-1 -> timedelta(days=-1, seconds=82800, microseconds=0)
 
193
        # Positive offsets have days=0
 
194
        return offset.days * 86400 + offset.seconds
115
195
 
116
196
 
117
197
class DateFormat(TimeFormat):
118
198
    year_days = [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
119
199
 
120
 
    def __init__(self, dt):
121
 
        # Accepts either a datetime or date object.
122
 
        self.data = dt
123
 
        self.timezone = None
124
 
        if isinstance(dt, datetime.datetime):
125
 
            if is_naive(dt):
126
 
                self.timezone = LocalTimezone(dt)
127
 
            else:
128
 
                self.timezone = dt.tzinfo
129
 
 
130
200
    def b(self):
131
201
        "Month, textual, 3 letters, lowercase; e.g. 'jan'"
132
202
        return MONTHS_3[self.data.month]
146
216
        "Day of the week, textual, 3 letters; e.g. 'Fri'"
147
217
        return WEEKDAYS_ABBR[self.data.weekday()]
148
218
 
149
 
    def e(self):
150
 
        "Timezone name if available"
151
 
        try:
152
 
            if hasattr(self.data, 'tzinfo') and self.data.tzinfo:
153
 
                # Have to use tzinfo.tzname and not datetime.tzname
154
 
                # because datatime.tzname does not expect Unicode
155
 
                return self.data.tzinfo.tzname(self.data) or ""
156
 
        except NotImplementedError:
157
 
            pass
158
 
        return ""
159
 
 
160
219
    def E(self):
161
220
        "Alternative month names as required by some locales. Proprietary extension."
162
221
        return MONTHS_ALT[self.data.month]
204
263
        "ISO 8601 year number matching the ISO week number (W)"
205
264
        return self.data.isocalendar()[0]
206
265
 
207
 
    def O(self):
208
 
        "Difference to Greenwich time in hours; e.g. '+0200', '-0430'"
209
 
        seconds = self.Z()
210
 
        sign = '-' if seconds < 0 else '+'
211
 
        seconds = abs(seconds)
212
 
        return "%s%02d%02d" % (sign, seconds // 3600, (seconds // 60) % 60)
213
 
 
214
266
    def r(self):
215
267
        "RFC 2822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'"
216
268
        return self.format('D, j M Y H:i:s O')
217
269
 
218
270
    def S(self):
219
271
        "English ordinal suffix for the day of the month, 2 characters; i.e. 'st', 'nd', 'rd' or 'th'"
220
 
        if self.data.day in (11, 12, 13): # Special case
 
272
        if self.data.day in (11, 12, 13):  # Special case
221
273
            return 'th'
222
274
        last = self.data.day % 10
223
275
        if last == 1:
232
284
        "Number of days in the given month; i.e. '28' to '31'"
233
285
        return '%02d' % calendar.monthrange(self.data.year, self.data.month)[1]
234
286
 
235
 
    def T(self):
236
 
        "Time zone of this machine; e.g. 'EST' or 'MDT'"
237
 
        name = self.timezone.tzname(self.data) if self.timezone else None
238
 
        if name is None:
239
 
            name = self.format('O')
240
 
        return six.text_type(name)
241
 
 
242
287
    def U(self):
243
288
        "Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)"
244
289
        if isinstance(self.data, datetime.datetime) and is_aware(self.data):
258
303
        weekday = self.data.weekday() + 1
259
304
        day_of_year = self.z()
260
305
        if day_of_year <= (8 - jan1_weekday) and jan1_weekday > 4:
261
 
            if jan1_weekday == 5 or (jan1_weekday == 6 and calendar.isleap(self.data.year-1)):
 
306
            if jan1_weekday == 5 or (jan1_weekday == 6 and calendar.isleap(self.data.year - 1)):
262
307
                week_number = 53
263
308
            else:
264
309
                week_number = 52
291
336
            doy += 1
292
337
        return doy
293
338
 
294
 
    def Z(self):
295
 
        """
296
 
        Time zone offset in seconds (i.e. '-43200' to '43200'). The offset for
297
 
        timezones west of UTC is always negative, and for those east of UTC is
298
 
        always positive.
299
 
        """
300
 
        if not self.timezone:
301
 
            return 0
302
 
        offset = self.timezone.utcoffset(self.data)
303
 
        # `offset` is a datetime.timedelta. For negative values (to the west of
304
 
        # UTC) only days can be negative (days=-1) and seconds are always
305
 
        # positive. e.g. UTC-1 -> timedelta(days=-1, seconds=82800, microseconds=0)
306
 
        # Positive offsets have days=0
307
 
        return offset.days * 86400 + offset.seconds
308
339
 
309
340
def format(value, format_string):
310
341
    "Convenience function"
311
342
    df = DateFormat(value)
312
343
    return df.format(format_string)
313
344
 
 
345
 
314
346
def time_format(value, format_string):
315
347
    "Convenience function"
316
348
    tf = TimeFormat(value)