3

In a Django ModelForm's DateTimeField I want to have an input_format that accepts a datetime with milliseconds. e.g. '2018-02-26T14:46:15.704Z'. But strftime only has %f for microseconds. How do I add an input_format to cope with this format?

My field so far:

class MyModelForm(forms.ModelForm):

    my_time  = forms.DateTimeField(input_formats=['%Y-%m-%dT%H:%M:%S.%fZ',])

This will match:

'2018-02-26T14:46:15.000704Z'

but not:

'2018-02-26T14:46:15.704Z'

Phil Gyford
  • 13,432
  • 14
  • 81
  • 143
  • You probably want to do this when cleaning the field. IE provide a `clean_my_time` method that will do the parsing 'manually'. [This question](https://stackoverflow.com/questions/27552780/django-validate-date-time-in-forms) grazes this topic. Let me know if you think that may work. – sytech Feb 26 '18 at 20:01
  • @sytech Good thinking, thanks. For now I've "fixed" the submitted data before processing the form but your suggestion is probably neater. It's just frustrating there's almost a built-in way to do this (`input_format`) but it can't work for this situation. – Phil Gyford Feb 26 '18 at 21:26
  • If you want this logic applied every time you use this datetime field, you could subclass `DateTimeField` and create your own that accepts your desired input format. That way, you won't have to implement such a solution on all your forms or views, possibly prevent a lot of code duplication if you have many forms that you want this behavior on. – sytech Feb 27 '18 at 14:50
  • I can formulate an answer for you covering these methods. But first, can you tell me what is complicated or unexpected about the current results you're getting using that format? If you do `'2018-02-26T14:46:15.704Z'` the default behavior should translate to a datetime with `704000` microseconds (or 704 milliseconds) which appears to be the behavior you want. With `'2018-02-26T14:46:15.000704Z'` the default behavior would result in a datetime with `704` microseconds. – sytech Feb 27 '18 at 15:46
  • 1
    Ahh... yes, you're right! Doh, I was so close to the details I didn't even think about how right-padding with zeros was actually the desired behaviour. Thanks. – Phil Gyford Feb 27 '18 at 17:24

1 Answers1

0

The default behavior of the %f with strptime will use right-padding for the microsecond field. So when you use the string '2018-02-26T14:46:15.704Z' with that format, you get the expected result that .704Z will translate to 704000 microseconds, which is 704 milliseconds as expected.

>>> fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
>>> datetimte.datetime.strptime('2018-02-26T14:46:15.704Z', fmt)
datetime.datetime(2018, 2, 26, 14, 46, 15, 704000)

So, in short, you already have your desired behavior.

sytech
  • 29,298
  • 3
  • 45
  • 86