Opened 3 years ago

Closed 3 years ago

#33066 closed Cleanup/optimization (wontfix)

Add annotation about accepting ISO 8601 formats by DateTimeField() to the DATETIME_INPUT_FORMATS docs.

Reported by: Christian Reksten-Monsen Owned by: nobody
Component: Documentation Version: 3.2
Severity: Normal Keywords: datetime iso8601
Cc: Claude Paroz Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

According to the documentation on DATETIME_INPUT_FORMATS, the given list of date time formats will be accepted when inputting data on a datetime field. My assumption is that Django will ONLY accept formats from this list (and also DATE_INPUT_FORMATS, as mentioned in the docs). Django will, however, also accept ISO 8601 date inputs, even though these formats are not present in DATETIME_INPUT_FORMATS. This is not mentioned in the docs.

This is because of PR #11893 for ticket 11385 which added support for ISO 8601 date inputs. ISO 8601 matching is done in DateTimeField and if there is a match, the BaseTemporalField to_python method (which checks date time format against DATETIME_INPUT_FORMATS) is never called.

This was confusing for me when unit testing a form field, a validation error was not raised when giving a date format that was not present in DATETIME_INPUT_FORMATS. Below test case replicates the issue.

Possible solutions:

  • Add the date time format (with timezone format, which I believe was the issue) to DATETIME_INPUT_FORMATS default. Python 2.7 and 3 strptime() do support %z.
  • Ignore it and update the docs that ISO 8601 date time formats will be accepted, regardless of not being present in DATETIME_INPUT_FORMATS.
  • Set a flag to strictly adhere DATETIME_INPUT_FORMATS or also allow ISO 8601 date time formats.
from datetime import datetime
from django.core.exceptions import ValidationError
from <app_name>.settings import DATETIME_INPUT_FORMATS

from django.test import TestCase
class TestDateTimeField(TestCase):
    def test_field_validation(self):
        with self.settings(DATETIME_INPUT_FORMATS=['%d/%m/%Y %H:%M']):
            field = DateTimeField(required=True)
            self.assertIsInstance(field.clean("31/12/2021 14:30"), datetime)
            with self.assertRaises(ValidationError):
                field.clean("2021-12-31 14:30")

Change History (3)

comment:1 by Christian Reksten-Monsen, 3 years ago

Reading the docs on form DateTimeField, its seems that the intended functionality is for the field to always accept ISO formats.

The field always accepts strings in ISO 8601 formatted dates or similar recognized by parse_datetime().

I therefore suggest to add clarification on this to the DATETIME_INPUT_FORMAT docs. Maybe just simply adding below text to the Changed in Django 3.1 callout:

Support for ISO 8601 date string parsing (including optional timezone) was added to DateTimeField form fields. The field always accepts strings in ISO 8601 formatted dates or similar recognized by parse_datetime(). The field will fallback on DATETIME_INPUT_FORMATS.

I have modified this ticket to reflect this being a documentation cleanup.

comment:2 by Christian Reksten-Monsen, 3 years ago

Component: FormsDocumentation
Type: BugCleanup/optimization

comment:3 by Mariusz Felisiak, 3 years ago

Cc: Claude Paroz added
Resolution: wontfix
Status: newclosed
Summary: DateTimeField does not exclusively validate the date time format against DATETIME_INPUT_FORMATSAdd annotation about accepting ISO 8601 formats by DateTimeField() to the DATETIME_INPUT_FORMATS docs.

Thanks for the ticket, however this change is related with DateTimeField not with the DATETIME_INPUT_FORMATS setting itself, its docs are still valid. We normally don't include such versionchanged annotations and I don't think this case is somehow special.

Note: See TracTickets for help on using tickets.
Back to Top