Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #479 -- Implemented time-zone formats in dateformat. Thanks, Sune

git-svn-id: http://code.djangoproject.com/svn/django/trunk@992 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 17f62269c2168549b76ee6204a1423a6e6f4e5f5 1 parent f82e64c
Adrian Holovaty adrianholovaty authored
37 django/utils/dateformat.py
View
@@ -12,8 +12,9 @@
"""
from django.utils.dates import MONTHS, MONTHS_AP, WEEKDAYS
+from django.utils.tzinfo import LocalTimezone
from calendar import isleap
-import re
+import re, time
re_formatchars = re.compile(r'(?<!\\)([aABdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])')
re_escaped = re.compile(r'\\(.)')
@@ -40,7 +41,9 @@ def a(self):
def A(self):
"'AM' or 'PM'"
- return self.a().upper()
+ if self.data.hour > 11:
+ return 'PM'
+ return 'AM'
def B(self):
"Swatch Internet time"
@@ -100,8 +103,12 @@ def s(self):
class DateFormat(TimeFormat):
year_days = [None, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
- def __init__(self, d):
- self.data = d
+ def __init__(self, dt):
+ # Accepts either a datetime or date object.
+ self.data = dt
+ self.timezone = getattr(dt, 'tzinfo', None)
+ if hasattr(self.data, 'hour') and not self.timezone:
+ self.timezone = LocalTimezone(dt)
def d(self):
"Day of the month, 2 digits with leading zeros; i.e. '01' to '31'"
@@ -119,6 +126,13 @@ def I(self):
"'1' if Daylight Savings Time, '0' otherwise."
raise NotImplementedError
+ def I(self):
+ "'1' if Daylight Savings Time, '0' otherwise."
+ if self.timezone.dst(self.data):
+ return '1'
+ else:
+ return '0'
+
def j(self):
"Day of the month without leading zeros; i.e. '1' to '31'"
return self.data.day
@@ -149,11 +163,12 @@ def N(self):
def O(self):
"Difference to Greenwich time in hours; e.g. '+0200'"
- raise NotImplementedError
+ tz = self.timezone.utcoffset(self.data)
+ return "%+03d%02d" % (tz.seconds // 3600, (tz.seconds // 60) % 60)
def r(self):
"RFC 822 formatted date; e.g. 'Thu, 21 Dec 2000 16:01:07 +0200'"
- raise NotImplementedError
+ return self.format('D, j M Y H:i:s O')
def S(self):
"English ordinal suffix for the day of the month, 2 characters; i.e. 'st', 'nd', 'rd' or 'th'"
@@ -174,11 +189,15 @@ def t(self):
def T(self):
"Time zone of this machine; e.g. 'EST' or 'MDT'"
- raise NotImplementedError
+ name = self.timezone.tzname(self.data)
+ if name is None:
+ name = self.format('O')
+ return name
def U(self):
"Seconds since the Unix epoch (January 1 1970 00:00:00 GMT)"
- raise NotImplementedError
+ off = self.timezone.utcoffset(self.data)
+ return int(time.mktime(self.data.timetuple())) + off.seconds * 60
def w(self):
"Day of the week, numeric, i.e. '0' (Sunday) to '6' (Saturday)"
@@ -229,7 +248,7 @@ def Z(self):
"""Time zone offset in seconds (i.e. '-43200' to '43200'). The offset
for timezones west of UTC is always negative, and for those east of UTC
is always positive."""
- raise NotImplementedError
+ return self.timezone.utcoffset(self.data).seconds
def format(value, format_string):
"Convenience function"
18 django/utils/timesince.py
View
@@ -1,4 +1,5 @@
-import time, math, datetime
+import datetime, math, time
+from django.utils.tzinfo import LocalTimezone
def timesince(d, now=None):
"""
@@ -6,7 +7,6 @@ def timesince(d, now=None):
as a nicely formatted string, e.g "10 minutes"
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
"""
- original = time.mktime(d.timetuple())
chunks = (
(60 * 60 * 24 * 365, 'year'),
(60 * 60 * 24 * 30, 'month'),
@@ -14,9 +14,17 @@ def timesince(d, now=None):
(60 * 60, 'hour'),
(60, 'minute')
)
- if not now:
- now = time.time()
- since = now - original
+ if now:
+ t = time.mktime(now)
+ else:
+ t = time.localtime()
+ if d.tzinfo:
+ tz = LocalTimezone()
+ else:
+ tz = None
+ now = datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5], tzinfo=tz)
+ delta = now - d
+ since = delta.days * 24 * 60 * 60 + delta.seconds
# Crazy iteration syntax because we need i to be current index
for i, (seconds, name) in zip(range(len(chunks)), chunks):
count = math.floor(since / seconds)
52 django/utils/tzinfo.py
View
@@ -0,0 +1,52 @@
+"Implementation of tzinfo classes for use with datetime.datetime."
+
+import time
+from datetime import timedelta, tzinfo
+
+class FixedOffset(tzinfo):
+ "Fixed offset in minutes east from UTC."
+ def __init__(self, offset):
+ self.__offset = timedelta(minutes=offset)
+ self.__name = "%+03d%02d" % (offset // 60, offset % 60)
+
+ def __repr__(self):
+ return self.__name
+
+ def utcoffset(self, dt):
+ return self.__offset
+
+ def tzname(self, dt):
+ return self.__name
+
+ def dst(self, dt):
+ return timedelta(0)
+
+class LocalTimezone(tzinfo):
+ "Proxy timezone information from time module."
+ def __init__(self, dt):
+ tzinfo.__init__(self, dt)
+ self._tzname = time.tzname[self._isdst(dt)]
+
+ def __repr__(self):
+ return self._tzname
+
+ def utcoffset(self, dt):
+ if self._isdst(dt):
+ return timedelta(seconds=-time.altzone)
+ else:
+ return timedelta(seconds=-time.timezone)
+
+ def dst(self, dt):
+ if self._isdst(dt):
+ return timedelta(seconds=-time.altzone) - timedelta(seconds=-time.timezone)
+ else:
+ return timedelta(0)
+
+ def tzname(self, dt):
+ return time.tzname[self._isdst(dt)]
+
+ def _isdst(self, dt):
+ tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1)
+ stamp = time.mktime(tt)
+ tt = time.localtime(stamp)
+ return tt.tm_isdst > 0
11 docs/templates.txt
View
@@ -517,18 +517,18 @@ Built-in tag reference
n Month without leading zeros. ``'1'`` to ``'12'``
N Month abbreviation in Associated Press ``'Jan.'``, ``'Feb.'``, ``'March'``, ``'May'``
style. Proprietary extension.
- O Not implemented.
+ O Difference to Greenwich time in hours. ``'+0200'``
P Time, in 12-hour hours, minutes and ``'1 a.m.'``, ``'1:30 p.m.'``, ``'midnight'``, ``'noon'``, ``'12:30 p.m.'``
'a.m.'/'p.m.', with minutes left off
if they're zero and the special-case
strings 'midnight' and 'noon' if
appropriate. Proprietary extension.
- r Not implemented.
+ r RFC 822 formatted date. ``'Thu, 21 Dec 2000 16:01:07 +0200'``
s Seconds, 2 digits with leading zeros. ``'00'`` to ``'59'``
S English ordinal suffix for day of the ``'st'``, ``'nd'``, ``'rd'`` or ``'th'``
month, 2 characters.
t Not implemented.
- T Not implemented.
+ T Time zone of this machine. ``'EST'``, ``'MDT'``
U Not implemented.
w Day of the week, digits without ``'0'`` (Sunday) to ``'6'`` (Saturday)
leading zeros.
@@ -537,7 +537,10 @@ Built-in tag reference
y Year, 2 digits. ``'99'``
Y Year, 4 digits. ``'1999'``
z Day of the year. ``0`` to ``365``
- Z Not implemented.
+ Z Time zone offset in seconds. The ``-43200`` to ``43200``
+ offset for timezones west of UTC is
+ always negative, and for those east of
+ UTC is always positive.
================ ====================================== =====================
Example::
75 tests/othertests/dateformat.py
View
@@ -0,0 +1,75 @@
+"""
+>>> format(my_birthday, '')
+''
+>>> format(my_birthday, 'a')
+'p.m.'
+>>> format(my_birthday, 'A')
+'PM'
+>>> format(my_birthday, 'j')
+'7'
+>>> format(my_birthday, 'l')
+'Saturday'
+>>> format(my_birthday, 'L')
+'False'
+>>> format(my_birthday, 'm')
+'07'
+>>> format(my_birthday, 'M')
+'Jul'
+>>> format(my_birthday, 'n')
+'7'
+>>> format(my_birthday, 'N')
+'July'
+>>> format(my_birthday, 'O')
+'+0100'
+>>> format(my_birthday, 'P')
+'10 p.m.'
+>>> format(my_birthday, 'r')
+'Sat, 7 Jul 1979 22:00:00 +0100'
+>>> format(my_birthday, 's')
+'00'
+>>> format(my_birthday, 'S')
+'th'
+>>> format(my_birthday, 't')
+Traceback (most recent call last):
+ ...
+NotImplementedError
+>>> format(my_birthday, 'T')
+'CET'
+>>> format(my_birthday, 'U')
+'300445200'
+>>> format(my_birthday, 'w')
+'6'
+>>> format(my_birthday, 'W')
+'27'
+>>> format(my_birthday, 'y')
+'79'
+>>> format(my_birthday, 'Y')
+'1979'
+>>> format(my_birthday, 'z')
+'188'
+>>> format(my_birthday, 'Z')
+'3600'
+
+>>> format(summertime, 'I')
+'1'
+>>> format(summertime, 'O')
+'+0200'
+>>> format(wintertime, 'I')
+'0'
+>>> format(wintertime, 'O')
+'+0100'
+
+>>> format(my_birthday, 'Y z \\C\\E\\T')
+'1979 188 CET'
+"""
+
+from django.utils import dateformat
+format = dateformat.format
+import datetime, os, time
+
+os.environ['TZ'] = 'Europe/Copenhagen'
+time.tzset()
+
+my_birthday = datetime.datetime(1979, 7, 7, 22, 00)
+summertime = datetime.datetime(2005, 10, 30, 1, 00)
+wintertime = datetime.datetime(2005, 10, 30, 4, 00)
Please sign in to comment.
Something went wrong with that request. Please try again.