Commit 9b1cb755 authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

Added support for time zones. Thanks Luke Plant for the review. Fixed #2626.

For more information on this project, see this thread:
http://groups.google.com/group/django-developers/browse_thread/thread/cf0423bbb85b1bbf



git-svn-id: http://code.djangoproject.com/svn/django/trunk@17106 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 01f70349
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -31,9 +31,13 @@ INTERNAL_IPS = ()

# Local time zone for this installation. All choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name (although not all
# systems may support all possibilities).
# systems may support all possibilities). When USE_TZ is True, this is
# interpreted as the default user time zone.
TIME_ZONE = 'America/Chicago'

# If you set this to True, Django will use timezone-aware datetimes.
USE_TZ = False

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'
@@ -119,7 +123,7 @@ LOCALE_PATHS = ()
LANGUAGE_COOKIE_NAME = 'django_language'

# If you set this to True, Django will format dates, numbers and calendars
# according to user current locale
# according to user current locale.
USE_L10N = False

# Not-necessarily-technical managers of the site. They get broken link
@@ -192,6 +196,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
#    'django.core.context_processors.request',
    'django.contrib.messages.context_processors.messages',
)
+4 −1
Original line number Diff line number Diff line
@@ -40,9 +40,12 @@ SITE_ID = 1
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''
+3 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ from django.utils import formats
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from django.utils import timezone
from django.utils.encoding import force_unicode, smart_unicode, smart_str
from django.utils.translation import ungettext
from django.core.urlresolvers import reverse
@@ -293,6 +294,8 @@ def display_for_field(value, field):
        return _boolean_icon(value)
    elif value is None:
        return EMPTY_CHANGELIST_VALUE
    elif isinstance(field, models.DateTimeField):
        return formats.localize(timezone.aslocaltime(value))
    elif isinstance(field, models.DateField) or isinstance(field, models.TimeField):
        return formats.localize(value)
    elif isinstance(field, models.DecimalField):
+5 −13
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@ from django.template import defaultfilters
from django.utils.encoding import force_unicode
from django.utils.formats import number_format
from django.utils.translation import pgettext, ungettext, ugettext as _
from django.utils.tzinfo import LocalTimezone
from django.utils.timezone import is_aware, utc

register = template.Library()

@@ -158,8 +158,8 @@ def naturalday(value, arg=None):
    except ValueError:
        # Date arguments out of range
        return value
    today = datetime.now(tzinfo).replace(microsecond=0, second=0, minute=0, hour=0)
    delta = value - today.date()
    today = datetime.now(tzinfo).date()
    delta = value - today
    if delta.days == 0:
        return _(u'today')
    elif delta.days == 1:
@@ -174,18 +174,10 @@ def naturaltime(value):
    For date and time values shows how many seconds, minutes or hours ago
    compared to current timestamp returns representing string.
    """
    try:
        value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second)
    except AttributeError:
        return value
    except ValueError:
    if not isinstance(value, date): # datetime is a subclass of date
        return value

    if getattr(value, 'tzinfo', None):
        now = datetime.now(LocalTimezone(value))
    else:
        now = datetime.now()
    now = now - timedelta(0, 0, now.microsecond)
    now = datetime.now(utc if is_aware(value) else None)
    if value < now:
        delta = now - value
        if delta.days != 0:
+42 −30
Original line number Diff line number Diff line
from __future__ import with_statement
from datetime import timedelta, date, datetime
import datetime

from django.template import Template, Context, defaultfilters
from django.test import TestCase
from django.utils import translation, tzinfo
from django.utils.translation import ugettext as _
from django.utils.html import escape
from django.utils.timezone import utc


class HumanizeTests(TestCase):
@@ -88,10 +89,10 @@ class HumanizeTests(TestCase):
        self.humanize_tester(test_list, result_list, 'apnumber')

    def test_naturalday(self):
        today = date.today()
        yesterday = today - timedelta(days=1)
        tomorrow = today + timedelta(days=1)
        someday = today - timedelta(days=10)
        today = datetime.date.today()
        yesterday = today - datetime.timedelta(days=1)
        tomorrow = today + datetime.timedelta(days=1)
        someday = today - datetime.timedelta(days=10)
        notdate = u"I'm not a date value"

        test_list = (today, yesterday, tomorrow, someday, notdate, None)
@@ -103,41 +104,46 @@ class HumanizeTests(TestCase):
    def test_naturalday_tz(self):
        from django.contrib.humanize.templatetags.humanize import naturalday

        today = date.today()
        tz_one = tzinfo.FixedOffset(timedelta(hours=-12))
        tz_two = tzinfo.FixedOffset(timedelta(hours=12))
        today = datetime.date.today()
        tz_one = tzinfo.FixedOffset(datetime.timedelta(hours=-12))
        tz_two = tzinfo.FixedOffset(datetime.timedelta(hours=12))

        # Can be today or yesterday
        date_one = datetime(today.year, today.month, today.day, tzinfo=tz_one)
        date_one = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_one)
        naturalday_one = naturalday(date_one)
        # Can be today or tomorrow
        date_two = datetime(today.year, today.month, today.day, tzinfo=tz_two)
        date_two = datetime.datetime(today.year, today.month, today.day, tzinfo=tz_two)
        naturalday_two = naturalday(date_two)

        # As 24h of difference they will never be the same
        self.assertNotEqual(naturalday_one, naturalday_two)

    def test_naturaltime(self):
        class naive(datetime.tzinfo):
            def utcoffset(self, dt):
                return None
        # we're going to mock datetime.datetime, so use a fixed datetime
        now = datetime(2011, 8, 15)
        now = datetime.datetime(2011, 8, 15)
        test_list = [
            now,
            now - timedelta(seconds=1),
            now - timedelta(seconds=30),
            now - timedelta(minutes=1, seconds=30),
            now - timedelta(minutes=2),
            now - timedelta(hours=1, minutes=30, seconds=30),
            now - timedelta(hours=23, minutes=50, seconds=50),
            now - timedelta(days=1),
            now - timedelta(days=500),
            now + timedelta(seconds=1),
            now + timedelta(seconds=30),
            now + timedelta(minutes=1, seconds=30),
            now + timedelta(minutes=2),
            now + timedelta(hours=1, minutes=30, seconds=30),
            now + timedelta(hours=23, minutes=50, seconds=50),
            now + timedelta(days=1),
            now + timedelta(days=500),
            now - datetime.timedelta(seconds=1),
            now - datetime.timedelta(seconds=30),
            now - datetime.timedelta(minutes=1, seconds=30),
            now - datetime.timedelta(minutes=2),
            now - datetime.timedelta(hours=1, minutes=30, seconds=30),
            now - datetime.timedelta(hours=23, minutes=50, seconds=50),
            now - datetime.timedelta(days=1),
            now - datetime.timedelta(days=500),
            now + datetime.timedelta(seconds=1),
            now + datetime.timedelta(seconds=30),
            now + datetime.timedelta(minutes=1, seconds=30),
            now + datetime.timedelta(minutes=2),
            now + datetime.timedelta(hours=1, minutes=30, seconds=30),
            now + datetime.timedelta(hours=23, minutes=50, seconds=50),
            now + datetime.timedelta(days=1),
            now + datetime.timedelta(days=500),
            now.replace(tzinfo=naive()),
            now.replace(tzinfo=utc),
        ]
        result_list = [
            'now',
@@ -157,14 +163,20 @@ class HumanizeTests(TestCase):
            '23 hours from now',
            '1 day from now',
            '1 year, 4 months from now',
            'now',
            'now',
        ]

        # mock out datetime so these tests don't fail occasionally when the
        # test runs too slow
        class MockDateTime(datetime):
        class MockDateTime(datetime.datetime):
            @classmethod
            def now(self):
            def now(self, tz=None):
                if tz is None or tz.utcoffset(now) is None:
                    return now
                else:
                    # equals now.replace(tzinfo=utc)
                    return now.replace(tzinfo=tz) + tz.utcoffset(now)

        # naturaltime also calls timesince/timeuntil
        from django.contrib.humanize.templatetags import humanize
Loading