cmlenz@4: .. -*- mode: rst; encoding: utf-8 -*- cmlenz@4: cmlenz@126: =============== cmlenz@126: Date Formatting cmlenz@126: =============== cmlenz@4: cmlenz@4: cmlenz@4: .. contents:: Contents cmlenz@4: :depth: 2 cmlenz@4: .. sectnum:: cmlenz@4: cmlenz@4: cmlenz@20: When working with date and time information in Python, you commonly use the cmlenz@100: classes ``date``, ``datetime`` and/or ``time`` from the `datetime`_ package. cmlenz@20: Babel provides functions for locale-specific formatting of those objects in its cmlenz@42: ``dates`` module: cmlenz@42: cmlenz@100: .. _`datetime`: http://docs.python.org/lib/module-datetime.html cmlenz@100: cmlenz@42: .. code-block:: pycon cmlenz@20: cmlenz@20: >>> from datetime import date, datetime, time cmlenz@20: >>> from babel.dates import format_date, format_datetime, format_time cmlenz@20: cmlenz@20: >>> d = date(2007, 4, 1) cmlenz@20: >>> format_date(d, locale='en') cmlenz@20: u'Apr 1, 2007' cmlenz@20: >>> format_date(d, locale='de_DE') cmlenz@20: u'01.04.2007' cmlenz@20: cmlenz@20: As this example demonstrates, Babel will automatically choose a date format cmlenz@20: that is appropriate for the requested locale. cmlenz@20: cmlenz@20: The ``format_*()`` functions also accept an optional ``format`` argument, which cmlenz@20: allows you to choose between one of four format variations: cmlenz@20: cmlenz@20: * ``short``, cmlenz@20: * ``medium`` (the default), cmlenz@22: * ``long``, and cmlenz@22: * ``full``. cmlenz@20: cmlenz@42: For example: cmlenz@42: cmlenz@42: .. code-block:: pycon cmlenz@20: cmlenz@20: >>> format_date(d, format='short', locale='en') cmlenz@20: u'4/1/07' cmlenz@20: >>> format_date(d, format='long', locale='en') cmlenz@20: u'April 1, 2007' cmlenz@20: >>> format_date(d, format='full', locale='en') cmlenz@20: u'Sunday, April 1, 2007' cmlenz@20: cmlenz@20: cmlenz@20: Pattern Syntax cmlenz@126: ============== cmlenz@20: cmlenz@20: While Babel makes it simple to use the appropriate date/time format for a given cmlenz@20: locale, you can also force it to use custom patterns. Note that Babel uses cmlenz@20: different patterns for specifying number and date formats compared to the cmlenz@20: Python equivalents (such as ``time.strftime()``), which have mostly been cmlenz@20: inherited from C and POSIX. The patterns used in Babel are based on the cmlenz@20: `Locale Data Markup Language specification`_ (LDML), which defines them as cmlenz@20: follows: cmlenz@20: cmlenz@20: A date/time pattern is a string of characters, where specific strings of cmlenz@20: characters are replaced with date and time data from a calendar when formatting cmlenz@20: or used to generate data for a calendar when parsing. […] cmlenz@20: cmlenz@20: Characters may be used multiple times. For example, if ``y`` is used for the cmlenz@20: year, ``yy`` might produce "99", whereas ``yyyy`` produces "1999". For most cmlenz@20: numerical fields, the number of characters specifies the field width. For cmlenz@20: example, if ``h`` is the hour, ``h`` might produce "5", but ``hh`` produces cmlenz@20: "05". For some characters, the count specifies whether an abbreviated or full cmlenz@20: form should be used […] cmlenz@20: cmlenz@20: Two single quotes represent a literal single quote, either inside or outside cmlenz@20: single quotes. Text within single quotes is not interpreted in any way (except cmlenz@20: for two adjacent single quotes). cmlenz@20: cmlenz@42: For example: cmlenz@42: cmlenz@42: .. code-block:: pycon cmlenz@20: cmlenz@20: >>> d = date(2007, 4, 1) cmlenz@20: >>> format_date(d, "EEE, MMM d, ''yy", locale='en') cmlenz@20: u"Sun, Apr 1, '07" cmlenz@20: >>> format_date(d, "EEEE, d.M.yyyy", locale='de') cmlenz@20: u'Sonntag, 1.4.2007' cmlenz@20: cmlenz@20: >>> t = time(15, 30) cmlenz@20: >>> format_time(t, "hh 'o''clock' a", locale='en') cmlenz@20: u"03 o'clock PM" cmlenz@20: >>> format_time(t, 'H:mm a', locale='de') cmlenz@20: u'15:30 nachm.' cmlenz@20: cmlenz@20: >>> dt = datetime(2007, 4, 1, 15, 30) cmlenz@20: >>> format_datetime(dt, "yyyyy.MMMM.dd GGG hh:mm a", locale='en') cmlenz@20: u'02007.April.01 AD 03:30 PM' cmlenz@20: cmlenz@20: The syntax for custom datetime format patterns is described in detail in the cmlenz@20: the `Locale Data Markup Language specification`_. The following table is just a cmlenz@20: relatively brief overview. cmlenz@20: cmlenz@20: .. _`Locale Data Markup Language specification`: http://unicode.org/reports/tr35/#Date_Format_Patterns cmlenz@20: cmlenz@20: Date Fields cmlenz@20: ----------- cmlenz@20: cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Field | Symbol | Description | cmlenz@20: +==========+========+========================================================+ cmlenz@20: | Era | ``G`` | Replaced with the era string for the current date. One | cmlenz@20: | | | to three letters for the abbreviated form, four | cmlenz@20: | | | lettersfor the long form, five for the narrow form | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Year | ``y`` | Replaced by the year. Normally the length specifies | cmlenz@20: | | | the padding, but for two letters it also specifies the | cmlenz@20: | | | maximum length. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``Y`` | Same as ``y`` but uses the ISO year-week calendar. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``u`` | ?? | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Quarter | ``Q`` | Use one or two for the numerical quarter, three for | cmlenz@20: | | | the abbreviation, or four for the full name. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``q`` | Use one or two for the numerical quarter, three for | cmlenz@20: | | | the abbreviation, or four for the full name. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Month | ``M`` | Use one or two for the numerical month, three for the | cmlenz@20: | | | abbreviation, or four for the full name, or five for | cmlenz@20: | | | the narrow name. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``L`` | Use one or two for the numerical month, three for the | cmlenz@20: | | | abbreviation, or four for the full name, or 5 for the | cmlenz@20: | | | narrow name. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Week | ``w`` | Week of year. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``W`` | Week of month. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Day | ``d`` | Day of month. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``D`` | Day of year. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``F`` | Day of week in month. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``g`` | ?? | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Week day | ``E`` | Day of week. Use one through three letters for the | cmlenz@20: | | | short day, or four for the full name, or five for the | cmlenz@20: | | | narrow name. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``e`` | Local day of week. Same as E except adds a numeric | cmlenz@20: | | | value that will depend on the local starting day of | cmlenz@20: | | | the week, using one or two letters. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``c`` | ?? | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: cmlenz@20: Time Fields cmlenz@20: ----------- cmlenz@20: cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Field | Symbol | Description | cmlenz@20: +==========+========+========================================================+ cmlenz@20: | Period | ``a`` | AM or PM | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Hour | ``h`` | Hour [1-12]. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``H`` | Hour [0-23]. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``K`` | Hour [0-11]. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``k`` | Hour [1-24]. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Minute | ``m`` | Use one or two for zero places padding. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Second | ``s`` | Use one or two for zero places padding. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``S`` | Fractional second, rounds to the count of letters. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``A`` | Milliseconds in day. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: | Timezone | ``z`` | Use one to three letters for the short timezone or | cmlenz@20: | | | four for the full name. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``Z`` | Use one to three letters for RFC 822, four letters for | cmlenz@20: | | | GMT format. | cmlenz@20: | +--------+--------------------------------------------------------+ cmlenz@20: | | ``v`` | Use one letter for short wall (generic) time, four for | cmlenz@20: | | | long wall time. | cmlenz@235: | +--------+--------------------------------------------------------+ cmlenz@235: | | ``V`` | Same as ``z``, except that timezone abbreviations | cmlenz@235: | | | should be used regardless of whether they are in | cmlenz@235: | | | common use by the locale. | cmlenz@20: +----------+--------+--------------------------------------------------------+ cmlenz@20: cmlenz@20: cmlenz@396: Time Delta Formatting cmlenz@396: ===================== cmlenz@396: cmlenz@396: In addition to providing functions for formatting localized dates and times, cmlenz@396: the ``babel.dates`` module also provides a function to format the difference cmlenz@396: between two times, called a ''time delta''. These are usually represented as cmlenz@396: ``datetime.timedelta`` objects in Python, and it's also what you get when you cmlenz@396: subtract one ``datetime`` object from an other. cmlenz@396: cmlenz@396: The ``format_timedelta`` function takes a ``timedelta`` object and returns a cmlenz@396: human-readable representation. This happens at the cost of precision, as it cmlenz@396: chooses only the most significant unit (such as year, week, or hour) of the cmlenz@396: difference, and displays that: cmlenz@396: cmlenz@396: .. code-block:: pycon cmlenz@396: cmlenz@396: >>> from datetime import timedelta cmlenz@396: >>> from babel.dates import format_timedelta cmlenz@396: >>> delta = timedelta(days=6) cmlenz@396: >>> format_timedelta(delta, locale='en_US') cmlenz@396: u'1 week' cmlenz@396: cmlenz@396: The resulting strings are based from the CLDR data, and are properly cmlenz@396: pluralized depending on the plural rules of the locale and the calculated cmlenz@396: number of units. cmlenz@396: cmlenz@396: The function provides parameters for you to influence how this most significant cmlenz@396: unit is chosen: with ``threshold`` you set the value after which the cmlenz@396: presentation switches to the next larger unit, and with ``granularity`` you cmlenz@396: can limit the smallest unit to display: cmlenz@396: cmlenz@396: .. code-block:: pycon cmlenz@396: cmlenz@396: >>> delta = timedelta(days=6) cmlenz@396: >>> format_timedelta(delta, threshold=1.2, locale='en_US') cmlenz@396: u'6 days' cmlenz@396: >>> format_timedelta(delta, granularity='month', locale='en_US') cmlenz@397: u'1 month' cmlenz@396: cmlenz@396: cmlenz@257: Time-zone Support cmlenz@126: ================= cmlenz@31: cmlenz@33: Many of the verbose time formats include the time-zone, but time-zone cmlenz@33: information is not by default available for the Python ``datetime`` and cmlenz@33: ``time`` objects. The standard library includes only the abstract ``tzinfo`` cmlenz@33: class, which you need appropriate implementations for to actually use in your cmlenz@31: application. Babel includes a ``tzinfo`` implementation for UTC (Universal cmlenz@33: Time). cmlenz@33: cmlenz@33: For real time-zone support, it is strongly recommended that you use the cmlenz@31: third-party package `pytz`_, which includes the definitions of practically all cmlenz@31: of the time-zones used on the world, as well as important functions for cmlenz@42: reliably converting from UTC to local time, and vice versa: cmlenz@42: cmlenz@42: .. code-block:: pycon cmlenz@31: cmlenz@31: >>> from datetime import time cmlenz@36: >>> from pytz import timezone, utc cmlenz@36: >>> dt = datetime(2007, 04, 01, 15, 30, tzinfo=utc) cmlenz@36: >>> eastern = timezone('US/Eastern') cmlenz@36: >>> format_datetime(dt, 'H:mm Z', tzinfo=eastern, locale='en_US') cmlenz@36: u'11:30 -0400' cmlenz@31: cmlenz@31: The recommended approach to deal with different time-zones in a Python cmlenz@31: application is to always use UTC internally, and only convert from/to the users cmlenz@31: time-zone when accepting user input and displaying date/time data, respectively. cmlenz@36: You can use Babel together with ``pytz`` to apply a time-zone to any cmlenz@36: ``datetime`` or ``time`` object for display, leaving the original information cmlenz@42: unchanged: cmlenz@42: cmlenz@42: .. code-block:: pycon cmlenz@36: cmlenz@36: >>> british = timezone('Europe/London') cmlenz@36: >>> format_datetime(dt, 'H:mm zzzz', tzinfo=british, locale='en_US') cmlenz@36: u'16:30 British Summer Time' cmlenz@31: cmlenz@37: Here, the given UTC time is adjusted to the "Europe/London" time-zone, and cmlenz@37: daylight savings time is taken into account. Daylight savings time is also cmlenz@37: applied to ``format_time``, but because the actual date is unknown in that cmlenz@37: case, the current day is assumed to determine whether DST or standard time cmlenz@37: should be used. cmlenz@37: cmlenz@31: .. _`pytz`: http://pytz.sourceforge.net/ cmlenz@31: cmlenz@31: cmlenz@257: Localized Time-zone Names cmlenz@257: ------------------------- cmlenz@257: cmlenz@257: While the ``Locale`` class provides access to various locale display names cmlenz@257: related to time-zones, the process of building a localized name of a time-zone cmlenz@257: is actually quite complicated. Babel implements it in separately usable cmlenz@257: functions in the ``babel.dates`` module, most importantly the cmlenz@257: ``get_timezone_name`` function: cmlenz@257: cmlenz@257: .. code-block:: pycon cmlenz@257: cmlenz@257: >>> from pytz import timezone cmlenz@257: >>> from babel import Locale cmlenz@257: >>> from babel.dates import get_timezone_name cmlenz@257: cmlenz@257: >>> tz = timezone('Europe/Berlin') cmlenz@257: >>> get_timezone_name(tz, locale=Locale.parse('pt_PT')) cmlenz@257: u'Hor\xe1rio Alemanha' cmlenz@257: cmlenz@257: You can pass the function either a ``datetime.tzinfo`` object, or a cmlenz@257: ``datetime.date`` or ``datetime.datetime`` object. If you pass an actual date, cmlenz@257: the function will be able to take daylight savings time into account. If you cmlenz@257: pass just the time-zone, Babel does not know whether daylight savings time is cmlenz@257: in effect, so it uses a generic representation, which is useful for example to cmlenz@257: display a list of time-zones to the user. cmlenz@257: cmlenz@257: .. code-block:: pycon cmlenz@257: cmlenz@257: >>> from datetime import datetime cmlenz@257: cmlenz@257: >>> dt = tz.localize(datetime(2007, 8, 15)) cmlenz@257: >>> get_timezone_name(dt, locale=Locale.parse('de_DE')) cmlenz@257: u'Mitteleurop\xe4ische Sommerzeit' cmlenz@257: >>> get_timezone_name(tz, locale=Locale.parse('de_DE')) cmlenz@257: u'Deutschland' cmlenz@257: cmlenz@257: cmlenz@20: Parsing Dates cmlenz@126: ============= cmlenz@20: cmlenz@42: Babel can also parse date and time information in a locale-sensitive manner: cmlenz@42: cmlenz@42: .. code-block:: pycon cmlenz@20: cmlenz@20: >>> from babel.dates import parse_date, parse_datetime, parse_time cmlenz@257: cmlenz@257: .. note:: Date/time parsing is not properly implemented yet