* ``LANG``
"""
-from datetime import date, datetime, time
+from datetime import date, datetime, time, timedelta, tzinfo
from babel.core import Locale
-from babel.util import default_locale
+from babel.util import default_locale, UTC
__all__ = ['format_date', 'format_datetime', 'format_time', 'parse_date',
'parse_datetime', 'parse_time']
If you don't want to use the locale default formats, you can specify a
custom date pattern:
- >>> format_time(d, "EEE, MMM d, ''yy", locale='en')
+ >>> format_date(d, "EEE, MMM d, ''yy", locale='en')
u"Sun, Apr 1, '07"
:param date: the ``date`` or ``datetime`` object
pattern = parse_pattern(format)
return parse_pattern(format).apply(date, locale)
-def format_datetime(datetime, format='medium', locale=LC_TIME):
+def format_datetime(datetime, format='medium', tzinfo=UTC, locale=LC_TIME):
"""Returns a date formatted according to the given pattern.
:param datetime: the ``date`` object
:param format: one of "full", "long", "medium", or "short", or a custom
date/time pattern
+ :param tzinfo: the timezone to apply to the time for display
:param locale: a `Locale` object or a locale identifier
:rtype: `unicode`
"""
pattern = parse_pattern(format)
return parse_pattern(format).apply(datetime, locale)
-def format_time(time, format='medium', locale=LC_TIME):
+def format_time(time, format='medium', tzinfo=UTC, locale=LC_TIME):
"""Returns a time formatted according to the given pattern.
>>> t = time(15, 30)
>>> format_time(t, "hh 'o''clock' a", locale='en')
u"03 o'clock PM"
+ For any pattern requiring the display of the time-zone, the third-party
+ ``pytz`` package is needed to explicitly specify the time-zone:
+
+ >>> from pytz import timezone
+ >>> cet = timezone('Europe/Berlin')
+ >>> format_time(t, format='full', tzinfo=cet, locale='de_DE')
+ u'15:30 Uhr MEZ'
+
:param time: the ``time`` or ``datetime`` object
:param format: one of "full", "long", "medium", or "short", or a custom
date/time pattern
+ :param tzinfo: the time-zone to apply to the time for display
:param locale: a `Locale` object or a locale identifier
:rtype: `unicode`
time = datetime.fromtimestamp(time).time()
elif isinstance(time, datetime):
time = time.time()
+ if time.tzinfo is None:
+ time = time.replace(tzinfo=tzinfo)
locale = Locale.parse(locale)
if format in ('full', 'long', 'medium', 'short'):
format = get_time_format(format, locale=locale)
def __init__(self, value, locale):
assert isinstance(value, (date, datetime, time))
+ if isinstance(value, (datetime, time)) and value.tzinfo is None:
+ value = value.replace(tzinfo=UTC)
self.value = value
self.locale = Locale.parse(locale)
return self.format(self.value.minute, num)
elif char == 's':
return self.format(self.value.second, num)
+ elif char in ('z', 'Z', 'v'):
+ return self.format_timezone(char, num)
else:
raise KeyError('Unsupported date/time field %r' % char)
period = {0: 'am', 1: 'pm'}[int(self.value.hour > 12)]
return get_period_names(locale=self.locale)[period]
+ def format_timezone(self, char, num):
+ if char == 'z':
+ zone = self.value.tzinfo.zone
+ if num < 4:
+ return self.locale.time_zones[zone]['short'][
+ self.value.dst() and 'daylight' or 'standard'
+ ]
+ else:
+ return self.locale.time_zones[zone]['long'][
+ self.value.dst() and 'daylight' or 'standard'
+ ]
+
+ elif char == 'Z':
+ offset = self.value.utcoffset()
+ hours, seconds = divmod(offset.seconds, 3600)
+ minutes = seconds // 60
+ sign = '+'
+ if offset.seconds < 0:
+ sign = '-'
+ pattern = {3: '%s%02d%02d', 4: 'GMT %s%02d:%02d'}[max(3, num)]
+ return pattern % (sign, hours, minutes)
+
+ elif char == 'v':
+ raise NotImplementedError
+
def format(self, value, length):
return ('%%0%dd' % length) % value
"""Various utility classes and functions."""
+from datetime import tzinfo
import os
import re
-__all__ = ['default_locale', 'extended_glob', 'LazyProxy']
+__all__ = ['default_locale', 'extended_glob', 'relpath', 'LazyProxy', 'UTC']
__docformat__ = 'restructuredtext en'
def default_locale(kind=None):
if regex.match(filepath):
yield filepath
+
class LazyProxy(object):
"""Class for proxy objects that delegate to a specified function to evaluate
the actual object.
relpath = os.path.relpath
except AttributeError:
def relpath(path, start='.'):
+ """Compute the relative path to one path from another.
+
+ :return: the relative path
+ :rtype: `basestring`
+ """
start_list = os.path.abspath(start).split(os.sep)
path_list = os.path.abspath(path).split(os.sep)
rel_list = [os.path.pardir] * (len(start_list) - i) + path_list[i:]
return os.path.join(*rel_list)
+
+try:
+ from pytz import UTC
+except ImportError:
+ ZERO = timedelta(0)
+
+ class UTC(tzinfo):
+ """Simple `tzinfo` implementation for UTC."""
+
+ def __repr__(self):
+ return '<UTC>'
+
+ def __str__(self):
+ return 'UTC'
+
+ def utcoffset(self, dt):
+ return ZERO
+
+ def tzname(self, dt):
+ return 'UTC'
+
+ def dst(self, dt):
+ return ZERO
+
+ UTC = UTC()
+ """`tzinfo` object for UTC (Universal Time).
+
+ :type: `tzinfo`
+ """
+----------+--------+--------------------------------------------------------+
+Time-zone Support
+-----------------
+
+Many of the verbose default time formats include the time-zone, but the
+time-zone is not by default available for the Python ``datetime`` and ``time``
+objects. The standard library includes only the abstract ``tzinfo`` class,
+which you need appropriate implementations for to actually use in your
+application. Babel includes a ``tzinfo`` implementation for UTC (Universal
+Time). For actual time-zones, it is strongly recommended that you use the
+third-party package `pytz`_, which includes the definitions of practically all
+of the time-zones used on the world, as well as important functions for
+reliably converting from UTC to local time, and vice versa::
+
+ >>> from datetime import time
+ >>> t = time(15, 30)
+
+ >>> from pytz import timezone
+ >>> cet = timezone('Europe/Berlin')
+ >>> format_time(t, 'H:mm Z', tzinfo=cet, locale='de_DE')
+ u'15:30 +0100'
+
+The recommended approach to deal with different time-zones in a Python
+application is to always use UTC internally, and only convert from/to the users
+time-zone when accepting user input and displaying date/time data, respectively.
+
+ .. _`pytz`: http://pytz.sourceforge.net/
+
+
+
Parsing Dates
-------------