Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #10825: fixed the 'U' format code to dateformat (and the date/n…

…ow filter/tag). Thanks to gsong and mir.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10716 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 2af75b485db15a8494b040aa04337c052b896cca 1 parent f7d01c4
Jacob Kaplan-Moss authored
19  django/utils/dateformat.py
@@ -11,12 +11,13 @@
11 11
 >>>
12 12
 """
13 13
 
  14
+import re
  15
+import time
  16
+import calendar
14 17
 from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS, WEEKDAYS_ABBR
15 18
 from django.utils.tzinfo import LocalTimezone
16 19
 from django.utils.translation import ugettext as _
17 20
 from django.utils.encoding import force_unicode
18  
-from calendar import isleap, monthrange
19  
-import re, time
20 21
 
21 22
 re_formatchars = re.compile(r'(?<!\\)([aAbBdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])')
22 23
 re_escaped = re.compile(r'\\(.)')
@@ -146,7 +147,7 @@ def l(self):
146 147
 
147 148
     def L(self):
148 149
         "Boolean for whether it is a leap year; i.e. True or False"
149  
-        return isleap(self.data.year)
  150
+        return calendar.isleap(self.data.year)
150 151
 
151 152
     def m(self):
152 153
         "Month; i.e. '01' to '12'"
@@ -188,7 +189,7 @@ def S(self):
188 189
 
189 190
     def t(self):
190 191
         "Number of days in the given month; i.e. '28' to '31'"
191  
-        return u'%02d' % monthrange(self.data.year, self.data.month)[1]
  192
+        return u'%02d' % calendar.monthrange(self.data.year, self.data.month)[1]
192 193
 
193 194
     def T(self):
194 195
         "Time zone of this machine; e.g. 'EST' or 'MDT'"
@@ -199,8 +200,10 @@ def T(self):
199 200
 
200 201
     def U(self):
201 202
         "Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)"
202  
-        off = self.timezone and self.timezone.utcoffset(self.data) or 0
203  
-        return int(time.mktime(self.data.timetuple())) + off.seconds * 60
  203
+        if getattr(self.data, 'tzinfo', None):
  204
+            return int(calendar.timegm(self.data.utctimetuple()))
  205
+        else:
  206
+            return int(time.mktime(self.data.timetuple()))
204 207
 
205 208
     def w(self):
206 209
         "Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)"
@@ -214,12 +217,12 @@ def W(self):
214 217
         weekday = self.data.weekday() + 1
215 218
         day_of_year = self.z()
216 219
         if day_of_year <= (8 - jan1_weekday) and jan1_weekday > 4:
217  
-            if jan1_weekday == 5 or (jan1_weekday == 6 and isleap(self.data.year-1)):
  220
+            if jan1_weekday == 5 or (jan1_weekday == 6 and calendar.isleap(self.data.year-1)):
218 221
                 week_number = 53
219 222
             else:
220 223
                 week_number = 52
221 224
         else:
222  
-            if isleap(self.data.year):
  225
+            if calendar.isleap(self.data.year):
223 226
                 i = 366
224 227
             else:
225 228
                 i = 365
3  docs/ref/templates/builtins.txt
@@ -506,7 +506,8 @@ Available format strings:
506 506
                       month, 2 characters.
507 507
     t                 Number of days in the given month.        ``28`` to ``31``
508 508
     T                 Time zone of this machine.                ``'EST'``, ``'MDT'``
509  
-    U                 Not implemented.
  509
+    U                 Seconds since the Unix Epoch
  510
+                      (January 1 1970 00:00:00 UTC).
510 511
     w                 Day of the week, digits without           ``'0'`` (Sunday) to ``'6'`` (Saturday)
511 512
                       leading zeros.
512 513
     W                 ISO-8601 week number of year, with        ``1``, ``53``
2  tests/regressiontests/dateformat/tests.py
@@ -37,7 +37,7 @@
37 37
 u'31'
38 38
 >>> no_tz or format(my_birthday, 'T') == 'CET'
39 39
 True
40  
->>> no_tz or format(my_birthday, 'U') == '300531600'
  40
+>>> no_tz or format(my_birthday, 'U') == '300315600'
41 41
 True
42 42
 >>> format(my_birthday, 'w')
43 43
 u'0'
48  tests/regressiontests/utils/dateformat.py
... ...
@@ -0,0 +1,48 @@
  1
+"""
  2
+>>> from datetime import datetime, date
  3
+>>> from django.utils.dateformat import format
  4
+>>> from django.utils.tzinfo import FixedOffset, LocalTimezone
  5
+
  6
+# date
  7
+>>> d = date(2009, 5, 16)
  8
+>>> date.fromtimestamp(int(format(d, 'U'))) == d
  9
+True
  10
+
  11
+# Naive datetime
  12
+>>> dt = datetime(2009, 5, 16, 5, 30, 30)
  13
+>>> datetime.fromtimestamp(int(format(dt, 'U'))) == dt
  14
+True
  15
+
  16
+# datetime with local tzinfo
  17
+>>> ltz = LocalTimezone(datetime.now())
  18
+>>> dt = datetime(2009, 5, 16, 5, 30, 30, tzinfo=ltz)
  19
+>>> datetime.fromtimestamp(int(format(dt, 'U')), ltz) == dt
  20
+True
  21
+>>> datetime.fromtimestamp(int(format(dt, 'U'))) == dt.replace(tzinfo=None)
  22
+True
  23
+
  24
+# datetime with arbitrary tzinfo
  25
+>>> tz = FixedOffset(-510)
  26
+>>> ltz = LocalTimezone(datetime.now())
  27
+>>> dt = datetime(2009, 5, 16, 5, 30, 30, tzinfo=tz)
  28
+>>> datetime.fromtimestamp(int(format(dt, 'U')), tz) == dt
  29
+True
  30
+>>> datetime.fromtimestamp(int(format(dt, 'U')), ltz) == dt
  31
+True
  32
+>>> datetime.fromtimestamp(int(format(dt, 'U'))) == dt.astimezone(ltz).replace(tzinfo=None)
  33
+True
  34
+>>> datetime.fromtimestamp(int(format(dt, 'U')), tz).utctimetuple() == dt.utctimetuple()
  35
+True
  36
+>>> datetime.fromtimestamp(int(format(dt, 'U')), ltz).utctimetuple() == dt.utctimetuple()
  37
+True
  38
+
  39
+# Epoch
  40
+>>> utc = FixedOffset(0)
  41
+>>> udt = datetime(1970, 1, 1, tzinfo=utc)
  42
+>>> format(udt, 'U')
  43
+u'0'
  44
+"""
  45
+
  46
+if __name__ == "__main__":
  47
+    import doctest
  48
+    doctest.testmod()
2  tests/regressiontests/utils/tests.py
@@ -8,6 +8,7 @@
8 8
 
9 9
 import timesince
10 10
 import datastructures
  11
+import dateformat
11 12
 import itercompat
12 13
 from decorators import DecoratorFromMiddlewareTests
13 14
 
@@ -22,6 +23,7 @@
22 23
 __test__ = {
23 24
     'timesince': timesince,
24 25
     'datastructures': datastructures,
  26
+    'dateformat': dateformat,
25 27
     'itercompat': itercompat,
26 28
 }
27 29
 

0 notes on commit 2af75b4

Please sign in to comment.
Something went wrong with that request. Please try again.