Allow user to specify date_format
This commit is contained in:
parent
3bfea9f624
commit
75a7db6015
|
|
@ -409,9 +409,22 @@ For rendering date and datetime information, the following helper functions are
|
|||
|
||||
Both functions resolve their output using the following priority order:
|
||||
|
||||
1. **`fmt=` argument** — a [strftime format string](https://docs.python.org/3/library/datetime.html#format-codes). When provided, this takes full priority and the `locale` argument is ignored.
|
||||
2. **`locale=` argument** (or the default system locale setting) — when no `fmt` is given, Babel formats the value in a locale-aware *medium* style (e.g. `Jan 12, 2025` for `en-us`).
|
||||
3. **ISO 8601 fallback** — when neither `fmt` nor a locale is available, the value is returned in ISO format (e.g. `2025-01-12`).
|
||||
1. **`fmt=` argument** — a [strftime format string](https://docs.python.org/3/library/datetime.html#format-codes). When provided, this takes full priority; `locale` and `date_format` are ignored.
|
||||
2. **`locale=` argument** — when no `fmt` is given, Babel formats the value using the style set by `date_format` (default `medium`).
|
||||
3. **Server `LANGUAGE_CODE`** — used as the locale when no `locale=` argument is supplied.
|
||||
|
||||
#### Date Format Styles
|
||||
|
||||
The `date_format` argument controls how Babel renders the date when locale-aware formatting is used. The four named styles are:
|
||||
|
||||
| Style | `format_date` example (en-us, 2025-01-12) | `format_datetime` example (en-us, 2025-01-12 14:30) |
|
||||
| --- | --- | --- |
|
||||
| `full` | `Sunday, January 12, 2025` | `Sunday, January 12, 2025 at 2:30:00 PM UTC` |
|
||||
| `long` | `January 12, 2025` | `January 12, 2025 at 2:30:00 PM UTC` |
|
||||
| `medium` *(default)* | `Jan 12, 2025` | `Jan 12, 2025, 2:30:00 PM` |
|
||||
| `short` | `1/12/25` | `1/12/25, 2:30 PM` |
|
||||
|
||||
The exact output varies by locale — the table above uses `en-us`.
|
||||
|
||||
### format_date
|
||||
|
||||
|
|
@ -426,23 +439,25 @@ Both functions resolve their output using the following priority order:
|
|||
{% raw %}
|
||||
{% load report %}
|
||||
|
||||
<!-- ISO fallback (no fmt, no locale) -->
|
||||
<!-- Default: medium style, locale from LANGUAGE_CODE -->
|
||||
{% format_date my_date %}
|
||||
<!-- output: 2025-01-12 -->
|
||||
<!-- output (en-us): Jan 12, 2025 -->
|
||||
|
||||
<!-- Explicit strftime format string — locale is ignored -->
|
||||
<!-- Explicit strftime format string — locale and date_format are ignored -->
|
||||
{% format_date my_date fmt="%d/%m/%Y" %}
|
||||
<!-- output: 12/01/2025 -->
|
||||
|
||||
<!-- Locale-aware medium format -->
|
||||
<!-- Locale-aware, default medium style -->
|
||||
{% format_date my_date locale='en-us' %}
|
||||
<!-- output: Jan 12, 2025 -->
|
||||
|
||||
{% format_date my_date locale='de-de' %}
|
||||
<!-- output: 12.01.2025 -->
|
||||
<!-- Short style -->
|
||||
{% format_date my_date locale='en-us' date_format='short' %}
|
||||
<!-- output: 1/12/25 -->
|
||||
|
||||
<!-- Convert from a different timezone before formatting -->
|
||||
{% format_date my_date timezone="Australia/Sydney" locale='en-au' %}
|
||||
<!-- Full style -->
|
||||
{% format_date my_date locale='en-us' date_format='full' %}
|
||||
<!-- output: Sunday, January 12, 2025 -->
|
||||
|
||||
{% endraw %}
|
||||
```
|
||||
|
|
@ -460,20 +475,21 @@ Both functions resolve their output using the following priority order:
|
|||
{% raw %}
|
||||
{% load report %}
|
||||
|
||||
<!-- ISO fallback (no fmt, no locale) -->
|
||||
<!-- Default: medium style, locale from LANGUAGE_CODE -->
|
||||
{% format_datetime my_datetime %}
|
||||
<!-- output: 2025-01-12T14:30:00+00:00 -->
|
||||
<!-- output (en-us): Jan 12, 2025, 2:30:00 PM -->
|
||||
|
||||
<!-- Explicit strftime format — locale is ignored -->
|
||||
<!-- Explicit strftime format — locale and date_format are ignored -->
|
||||
{% format_datetime my_datetime fmt="%d-%m-%Y %H:%M" %}
|
||||
<!-- output: 12-01-2025 14:30 -->
|
||||
|
||||
<!-- Locale-aware medium format -->
|
||||
<!-- Locale-aware, default medium style -->
|
||||
{% format_datetime my_datetime locale='en-us' %}
|
||||
<!-- output: Jan 12, 2025, 2:30:00 PM -->
|
||||
|
||||
{% format_datetime my_datetime locale='de-de' %}
|
||||
<!-- output: 12.01.2025, 14:30:00 -->
|
||||
<!-- Short style -->
|
||||
{% format_datetime my_datetime locale='de-de' date_format='short' %}
|
||||
<!-- output: 12.01.25, 14:30 -->
|
||||
|
||||
<!-- Convert to a specific timezone before formatting -->
|
||||
{% format_datetime my_datetime timezone="Australia/Sydney" locale='en-au' %}
|
||||
|
|
|
|||
|
|
@ -982,6 +982,7 @@ def format_number(
|
|||
max_decimal_places: Optional[int] = None,
|
||||
fmt: Optional[str] = None,
|
||||
locale: Optional[str] = None,
|
||||
**kwargs,
|
||||
) -> str:
|
||||
"""Render a number with optional formatting options.
|
||||
|
||||
|
|
@ -1065,14 +1066,17 @@ def format_datetime(
|
|||
timezone: Optional[str] = None,
|
||||
fmt: Optional[str] = None,
|
||||
locale: Optional[str] = None,
|
||||
date_format: str = 'medium',
|
||||
**kwargs,
|
||||
):
|
||||
"""Format a datetime object for display.
|
||||
|
||||
Arguments:
|
||||
dt: The datetime object to format
|
||||
timezone: The timezone to use for the date (defaults to the server timezone)
|
||||
fmt: The strftime format string to use. When provided, takes priority over locale.
|
||||
fmt: The strftime format string to use. When provided, takes priority over locale and date_format.
|
||||
locale: Optional locale override (e.g. 'en-us', 'de-de'). Used for locale-aware formatting when no fmt is given.
|
||||
date_format: Babel date format style. One of 'full', 'long', 'medium' (default), 'short'.
|
||||
"""
|
||||
check_nulls('format_datetime', dt)
|
||||
|
||||
|
|
@ -1081,10 +1085,7 @@ def format_datetime(
|
|||
if fmt:
|
||||
return dt.strftime(fmt)
|
||||
|
||||
return babel_format_datetime(dt, format='medium', locale=get_locale(locale))
|
||||
|
||||
# Final backup - return an ISO formatted string
|
||||
return dt.isoformat()
|
||||
return babel_format_datetime(dt, format=date_format, locale=get_locale(locale))
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
|
|
@ -1093,14 +1094,17 @@ def format_date(
|
|||
timezone: Optional[str] = None,
|
||||
fmt: Optional[str] = None,
|
||||
locale: Optional[str] = None,
|
||||
date_format: str = 'medium',
|
||||
**kwargs,
|
||||
):
|
||||
"""Format a date object for display.
|
||||
|
||||
Arguments:
|
||||
dt: The date to format
|
||||
timezone: The timezone to use for the date (defaults to the server timezone)
|
||||
fmt: The strftime format string to use. When provided, takes priority over locale.
|
||||
fmt: The strftime format string to use. When provided, takes priority over locale and date_format.
|
||||
locale: Optional locale override (e.g. 'en-us', 'de-de'). Used for locale-aware formatting when no fmt is given.
|
||||
date_format: Babel date format style. One of 'full', 'long', 'medium' (default), 'short'.
|
||||
"""
|
||||
check_nulls('format_date', dt)
|
||||
|
||||
|
|
@ -1112,7 +1116,7 @@ def format_date(
|
|||
if fmt:
|
||||
return dt.strftime(fmt)
|
||||
|
||||
return babel_format_date(dt, format='medium', locale=get_locale(locale))
|
||||
return babel_format_date(dt, format=date_format, locale=get_locale(locale))
|
||||
|
||||
|
||||
@register.simple_tag()
|
||||
|
|
|
|||
|
|
@ -730,6 +730,25 @@ class ReportTagTest(PartImageTestMixin, InvenTreeTestCase):
|
|||
with override_settings(LANGUAGE_CODE='en-us'):
|
||||
self.assertEqual(report_tags.format_date(dt), 'Mar 13, 2024')
|
||||
|
||||
# date_format controls the Babel style
|
||||
self.assertEqual(
|
||||
report_tags.format_date(dt, locale='en-us', date_format='short'), '3/13/24'
|
||||
)
|
||||
self.assertEqual(
|
||||
report_tags.format_date(dt, locale='en-us', date_format='long'),
|
||||
'March 13, 2024',
|
||||
)
|
||||
self.assertEqual(
|
||||
report_tags.format_date(dt, locale='en-us', date_format='full'),
|
||||
'Wednesday, March 13, 2024',
|
||||
)
|
||||
|
||||
# fmt= wins over date_format=
|
||||
self.assertEqual(
|
||||
report_tags.format_date(dt, fmt='%Y', locale='en-us', date_format='full'),
|
||||
'2024',
|
||||
)
|
||||
|
||||
# Invalid locale raises ValidationError
|
||||
with self.assertRaises(ValidationError):
|
||||
report_tags.format_date(dt, locale='xx-zz')
|
||||
|
|
@ -758,6 +777,24 @@ class ReportTagTest(PartImageTestMixin, InvenTreeTestCase):
|
|||
with override_settings(LANGUAGE_CODE='de-de'):
|
||||
self.assertEqual(report_tags.format_datetime(dt), '19.06.2026, 15:30:00')
|
||||
|
||||
# date_format controls the Babel style
|
||||
self.assertEqual(
|
||||
report_tags.format_datetime(dt, locale='de-de', date_format='short'),
|
||||
'19.06.26, 15:30',
|
||||
)
|
||||
self.assertEqual(
|
||||
report_tags.format_datetime(dt, locale='de-de', date_format='long'),
|
||||
'19. Juni 2026 um 15:30:00 UTC', # codespell:ignore "Juni"
|
||||
)
|
||||
|
||||
# fmt= wins over date_format=
|
||||
self.assertEqual(
|
||||
report_tags.format_datetime(
|
||||
dt, fmt='%H:%M', locale='en-us', date_format='full'
|
||||
),
|
||||
'15:30',
|
||||
)
|
||||
|
||||
# Invalid locale raises ValidationError
|
||||
with self.assertRaises(ValidationError):
|
||||
report_tags.format_datetime(dt, locale='xx-zz')
|
||||
|
|
|
|||
Loading…
Reference in New Issue