Fixed #8809 -- ExcelDateFormatter generates invalid format strings (#8811)

The format strings generated previously would not work correctly in macOs Preview and Numbers
pull/8719/head
Jaap Roes 2022-07-07 09:30:20 +02:00 zatwierdzone przez Matt Westcott
rodzic d967eccef2
commit 12ba7d8161
4 zmienionych plików z 93 dodań i 37 usunięć

Wyświetl plik

@ -78,6 +78,7 @@ Changelog
* Fix: When no snippets are added, ensure the snippet chooser modal would have the correct URL for creating a new snippet (Matt Westcott)
* Fix: `ngettext` in Wagtail's internal JavaScript internationalisation utilities now works (LB (Ben) Johnston)
* Fix: Ensure the linting/formatting npm scripts work on Windows (Anuja Verma)
* Fix: Fix display of dates in exported xlsx files on macOS Preview and Numbers (Jaap Roes)
3.0.1 (16.06.2022)

Wyświetl plik

@ -90,6 +90,7 @@ When using a queryset to render a list of images, you can now use the `prefetch_
* When no snippets are added, ensure the snippet chooser modal would have the correct URL for creating a new snippet (Matt Westcott)
* `ngettext` in Wagtail's internal JavaScript internationalisation utilities now works (LB (Ben) Johnston)
* Ensure the linting/formatting npm scripts work on Windows (Anuja Verma)
* Fix display of dates in exported xlsx files on macOS Preview and Numbers (Jaap Roes)
## Upgrade considerations

Wyświetl plik

@ -262,6 +262,17 @@ class TestExcelDateFormatter(TestCase):
with self.subTest(lang), translation.override(lang):
self.assertNotEqual(formatter.get(), "")
def test_format(self):
formatter = ExcelDateFormatter()
with self.subTest(format="r"):
# Format code for RFC 5322 formatted date, e.g. 'Thu, 21 Dec 2000 16:01:07'
self.assertEqual(formatter.format("r"), "ddd, d mmm yyyy hh:mm:ss")
with self.subTest(format="m/d/Y g:i A"):
# Format code for e.g. '12/21/2000 4:01 PM'
self.assertEqual(formatter.format("m/d/Y g:i A"), "mm/dd/yyyy h:mm AM/PM")
class TestAgingPagesView(TestCase, WagtailTestUtils):
def setUp(self):

Wyświetl plik

@ -68,44 +68,87 @@ def list_to_str(value):
class ExcelDateFormatter(Formatter):
data = None
# From: https://docs.djangoproject.com/en/stable/ref/templates/builtins/#date
# To: https://support.microsoft.com/en-us/office/format-numbers-as-dates-or-times-418bd3fe-0577-47c8-8caa-b4d30c528309#bm2
_formats = {
"d": "DD",
"j": "D",
"D": "NN",
"l": "NNNN",
"S": "",
"w": "",
"z": "",
"W": "",
"m": "MM",
"n": "M",
"M": "MMM",
"b": "MMM",
"F": "MMMM",
"E": "MMM",
"N": "MMM.",
"y": "YY",
"Y": "YYYY",
"L": "",
"o": "",
"g": "H",
"G": "H",
"h": "HH",
"H": "HH",
"i": "MM",
"s": "SS",
"u": "",
"a": "AM/PM",
"A": "AM/PM",
"P": "HH:MM AM/PM",
"e": "",
"I": "",
"O": "",
"T": "",
"Z": "",
"c": "YYYY-MM-DD HH:MM:SS",
"r": "NN, MMM D YY HH:MM:SS",
"U": "[HH]:MM:SS",
# Day of the month, 2 digits with leading zeros.
"d": "dd",
# Day of the month without leading zeros.
"j": "d",
# Day of the week, textual, 3 letters.
"D": "ddd",
# Day of the week, textual, full.
"l": "dddd",
# English ordinal suffix for the day of the month, 2 characters.
"S": "", # Not supported in Excel
# Day of the week, digits without leading zeros.
"w": "", # Not supported in Excel
# Day of the year.
"z": "", # Not supported in Excel
# ISO-8601 week number of year, with weeks starting on Monday.
"W": "", # Not supported in Excel
# Month, 2 digits with leading zeros.
"m": "mm",
# Month without leading zeros.
"n": "m",
# Month, textual, 3 letters.
"M": "mmm",
# Month, textual, 3 letters, lowercase. (Not supported in Excel)
"b": "mmm",
# Month, locale specific alternative representation usually used for long date representation.
"E": "mmmm", # Not supported in Excel
# Month, textual, full.
"F": "mmmm",
# Month abbreviation in Associated Press style. Proprietary extension.
"N": "mmm.", # Approximation, wrong for May
# Number of days in the given month.
"t": "", # Not supported in Excel
# Year, 2 digits with leading zeros.
"y": "yy",
# Year, 4 digits with leading zeros.
"Y": "yyyy",
# Whether it's a leap year.
"L": "", # Not supported in Excel
# ISO-8601 week-numbering year.
"o": "yyyy", # Approximation, same as Y
# Hour, 12-hour format without leading zeros.
"g": "h", # Only works when combined with AM/PM, 24-hour format is used otherwise
# Hour, 24-hour format without leading zeros.
"G": "hH",
# Hour, 12-hour format with leading zeros.
"h": "hh", # Only works when combined with AM/PM, 24-hour format is used otherwise
# Hour, 24-hour format with leading zeros.
"H": "hh",
# Minutes.
"i": "mm",
# Seconds.
"s": "ss",
# Microseconds.
"u": ".00", # Only works when combined with ss
# 'a.m.' or 'p.m.'.
"a": "AM/PM", # Approximation, uses AM/PM and only works when combined with h/hh
# AM/PM.
"A": "AM/PM", # Only works when combined with h/hh
# Time, in 12-hour hours and minutes, with minutes left off if theyre zero.
"f": "h:mm", # Approximation, uses 24-hour format and minutes are never left off
# Time, in 12-hour hours, minutes and a.m./p.m., with minutes left off if theyre zero and the special-case strings midnight and noon if appropriate.
"P": "h:mm AM/PM", # Approximation, minutes are never left off, no special case strings
# Timezone name.
"e": "", # Not supported in Excel
# Daylight saving time, whether its in effect or not.
"I": "", # Not supported in Excel
# Difference to Greenwich time in hours.
"O": "", # Not supported in Excel
# Time zone of this machine.
"T": "", # Not supported in Excel
# Timezone offset in seconds.
"Z": "", # Not supported in Excel
# ISO 8601 format.
"c": "yyyy-mm-ddThh:mm:ss.00",
# RFC 5322 formatted date.
"r": "ddd, d mmm yyyy hh:mm:ss",
# Seconds since the Unix epoch.
"U": "", # Not supported in Excel
}
def get(self):