1. from datetime import date, datetime, timezone
    
  2. 
    
  3. from django.core.exceptions import ValidationError
    
  4. from django.forms import DateTimeField
    
  5. from django.test import SimpleTestCase
    
  6. from django.utils.timezone import get_fixed_timezone
    
  7. 
    
  8. 
    
  9. class DateTimeFieldTest(SimpleTestCase):
    
  10.     def test_datetimefield_clean(self):
    
  11.         tests = [
    
  12.             (date(2006, 10, 25), datetime(2006, 10, 25, 0, 0)),
    
  13.             (datetime(2006, 10, 25, 14, 30), datetime(2006, 10, 25, 14, 30)),
    
  14.             (datetime(2006, 10, 25, 14, 30, 59), datetime(2006, 10, 25, 14, 30, 59)),
    
  15.             (
    
  16.                 datetime(2006, 10, 25, 14, 30, 59, 200),
    
  17.                 datetime(2006, 10, 25, 14, 30, 59, 200),
    
  18.             ),
    
  19.             ("2006-10-25 14:30:45.000200", datetime(2006, 10, 25, 14, 30, 45, 200)),
    
  20.             ("2006-10-25 14:30:45.0002", datetime(2006, 10, 25, 14, 30, 45, 200)),
    
  21.             ("2006-10-25 14:30:45", datetime(2006, 10, 25, 14, 30, 45)),
    
  22.             ("2006-10-25 14:30:00", datetime(2006, 10, 25, 14, 30)),
    
  23.             ("2006-10-25 14:30", datetime(2006, 10, 25, 14, 30)),
    
  24.             ("2006-10-25", datetime(2006, 10, 25, 0, 0)),
    
  25.             ("10/25/2006 14:30:45.000200", datetime(2006, 10, 25, 14, 30, 45, 200)),
    
  26.             ("10/25/2006 14:30:45", datetime(2006, 10, 25, 14, 30, 45)),
    
  27.             ("10/25/2006 14:30:00", datetime(2006, 10, 25, 14, 30)),
    
  28.             ("10/25/2006 14:30", datetime(2006, 10, 25, 14, 30)),
    
  29.             ("10/25/2006", datetime(2006, 10, 25, 0, 0)),
    
  30.             ("10/25/06 14:30:45.000200", datetime(2006, 10, 25, 14, 30, 45, 200)),
    
  31.             ("10/25/06 14:30:45", datetime(2006, 10, 25, 14, 30, 45)),
    
  32.             ("10/25/06 14:30:00", datetime(2006, 10, 25, 14, 30)),
    
  33.             ("10/25/06 14:30", datetime(2006, 10, 25, 14, 30)),
    
  34.             ("10/25/06", datetime(2006, 10, 25, 0, 0)),
    
  35.             # ISO 8601 formats.
    
  36.             (
    
  37.                 "2014-09-23T22:34:41.614804",
    
  38.                 datetime(2014, 9, 23, 22, 34, 41, 614804),
    
  39.             ),
    
  40.             ("2014-09-23T22:34:41", datetime(2014, 9, 23, 22, 34, 41)),
    
  41.             ("2014-09-23T22:34", datetime(2014, 9, 23, 22, 34)),
    
  42.             ("2014-09-23", datetime(2014, 9, 23, 0, 0)),
    
  43.             ("2014-09-23T22:34Z", datetime(2014, 9, 23, 22, 34, tzinfo=timezone.utc)),
    
  44.             (
    
  45.                 "2014-09-23T22:34+07:00",
    
  46.                 datetime(2014, 9, 23, 22, 34, tzinfo=get_fixed_timezone(420)),
    
  47.             ),
    
  48.             # Whitespace stripping.
    
  49.             (" 2006-10-25   14:30:45 ", datetime(2006, 10, 25, 14, 30, 45)),
    
  50.             (" 2006-10-25 ", datetime(2006, 10, 25, 0, 0)),
    
  51.             (" 10/25/2006 14:30:45 ", datetime(2006, 10, 25, 14, 30, 45)),
    
  52.             (" 10/25/2006 14:30 ", datetime(2006, 10, 25, 14, 30)),
    
  53.             (" 10/25/2006 ", datetime(2006, 10, 25, 0, 0)),
    
  54.             (" 10/25/06 14:30:45 ", datetime(2006, 10, 25, 14, 30, 45)),
    
  55.             (" 10/25/06 ", datetime(2006, 10, 25, 0, 0)),
    
  56.             (
    
  57.                 " 2014-09-23T22:34:41.614804 ",
    
  58.                 datetime(2014, 9, 23, 22, 34, 41, 614804),
    
  59.             ),
    
  60.             (" 2014-09-23T22:34Z ", datetime(2014, 9, 23, 22, 34, tzinfo=timezone.utc)),
    
  61.         ]
    
  62.         f = DateTimeField()
    
  63.         for value, expected_datetime in tests:
    
  64.             with self.subTest(value=value):
    
  65.                 self.assertEqual(f.clean(value), expected_datetime)
    
  66. 
    
  67.     def test_datetimefield_clean_invalid(self):
    
  68.         f = DateTimeField()
    
  69.         msg = "'Enter a valid date/time.'"
    
  70.         with self.assertRaisesMessage(ValidationError, msg):
    
  71.             f.clean("hello")
    
  72.         with self.assertRaisesMessage(ValidationError, msg):
    
  73.             f.clean("2006-10-25 4:30 p.m.")
    
  74.         with self.assertRaisesMessage(ValidationError, msg):
    
  75.             f.clean("   ")
    
  76.         with self.assertRaisesMessage(ValidationError, msg):
    
  77.             f.clean("2014-09-23T28:23")
    
  78.         f = DateTimeField(input_formats=["%Y %m %d %I:%M %p"])
    
  79.         with self.assertRaisesMessage(ValidationError, msg):
    
  80.             f.clean("2006.10.25 14:30:45")
    
  81. 
    
  82.     def test_datetimefield_clean_input_formats(self):
    
  83.         tests = [
    
  84.             (
    
  85.                 "%Y %m %d %I:%M %p",
    
  86.                 (
    
  87.                     (date(2006, 10, 25), datetime(2006, 10, 25, 0, 0)),
    
  88.                     (datetime(2006, 10, 25, 14, 30), datetime(2006, 10, 25, 14, 30)),
    
  89.                     (
    
  90.                         datetime(2006, 10, 25, 14, 30, 59),
    
  91.                         datetime(2006, 10, 25, 14, 30, 59),
    
  92.                     ),
    
  93.                     (
    
  94.                         datetime(2006, 10, 25, 14, 30, 59, 200),
    
  95.                         datetime(2006, 10, 25, 14, 30, 59, 200),
    
  96.                     ),
    
  97.                     ("2006 10 25 2:30 PM", datetime(2006, 10, 25, 14, 30)),
    
  98.                     # ISO-like formats are always accepted.
    
  99.                     ("2006-10-25 14:30:45", datetime(2006, 10, 25, 14, 30, 45)),
    
  100.                 ),
    
  101.             ),
    
  102.             (
    
  103.                 "%Y.%m.%d %H:%M:%S.%f",
    
  104.                 (
    
  105.                     (
    
  106.                         "2006.10.25 14:30:45.0002",
    
  107.                         datetime(2006, 10, 25, 14, 30, 45, 200),
    
  108.                     ),
    
  109.                 ),
    
  110.             ),
    
  111.         ]
    
  112.         for input_format, values in tests:
    
  113.             f = DateTimeField(input_formats=[input_format])
    
  114.             for value, expected_datetime in values:
    
  115.                 with self.subTest(value=value, input_format=input_format):
    
  116.                     self.assertEqual(f.clean(value), expected_datetime)
    
  117. 
    
  118.     def test_datetimefield_not_required(self):
    
  119.         f = DateTimeField(required=False)
    
  120.         self.assertIsNone(f.clean(None))
    
  121.         self.assertEqual("None", repr(f.clean(None)))
    
  122.         self.assertIsNone(f.clean(""))
    
  123.         self.assertEqual("None", repr(f.clean("")))
    
  124. 
    
  125.     def test_datetimefield_changed(self):
    
  126.         f = DateTimeField(input_formats=["%Y %m %d %I:%M %p"])
    
  127.         d = datetime(2006, 9, 17, 14, 30, 0)
    
  128.         self.assertFalse(f.has_changed(d, "2006 09 17 2:30 PM"))