0

In my Python 3.6 application, from my input data I can receive datatimes in two different formats:

"datefield":"12/29/2017" or "datefield":"2017-12-31"

I need to make sure the that I can handle either datetime format and convert them to (or leave it in) the iso 8601 format. I want to do something like this:

#python pseudocode
import datetime
if datefield = "m%/d%/Y%":
  final_date = datetime.datetime.strptime(datefield, "%Y-%m-%d").strftime("%Y-%m-%d")
elif datefield = "%Y-%m-%d":
  final_date = datefield

The problem is I don't know how to check the datefield for a specific datetime format in that first if-statement in my pseudocode. I want a true or false back. I read through the Python docs and some tutorials. I did see one or two obscure examples that used try-except blocks, but that doesn't seem like an efficient way to handle this. This question is unique from other stack overflow posts because I need to handle and validate two different cases, not just one case, where I can simply fail it if it does validate.

Cale Sweeney
  • 1,014
  • 1
  • 15
  • 37
  • 4
    _"I read through the Python docs and some tutorials. I did see one or two obscure examples that used try-except blocks, but that doesn't seem like an efficient way to handle this."_ - Actually, using exceptions in Python is consider idiomatic and is often faster than an `if/else` block in many cases. Just FYI. – Christian Dean Dec 29 '17 at 01:40
  • Possible duplicate of [How do I validate a date string format in python?](https://stackoverflow.com/questions/16870663/how-do-i-validate-a-date-string-format-in-python) – Patrick Haugh Dec 29 '17 at 01:41
  • @PatrickHaugh I read that question, but I was thinking its not apples to apples because in my case I have two date formats that are not errors or exceptional cases. They are two common use cases that need to be handled and routed. – Cale Sweeney Dec 29 '17 at 01:48
  • 2
    @CaleSweeney There's nothing wrong or bad about using exceptions like this. As far as I know the `datetime` module doesn't provide this functionality directly, so the most straightforward way is through catching exceptions that `strptime` raises. – Patrick Haugh Dec 29 '17 at 01:59

4 Answers4

1

You can detect the first style of date by a simple string test, looking for the / separators. Depending on how "loose" you want the check to be, you could check a specific index or scan the whole string with a substring test using the in operator:

if "/" in datefield: # or "if datefield[2] = '/'", or maybe "if datefield[-5] = '/'"
    final_date = datetime.datetime.strptime(datefield, "%m/%d/%Y").strftime("%Y-%m-%d")
Blckknght
  • 100,903
  • 11
  • 120
  • 169
  • Checking for individual characters could work, but does Python's datetime library have a function that I could use to test format just in case I am faced with new alternative datetime format in the future? – Cale Sweeney Dec 29 '17 at 01:54
  • I don't think so, other than the parsing functions. That *is* a pretty reasonable option though: just try to parse it and if it works, you've validated the input. If not, you catch the exception and try something else. – Blckknght Dec 29 '17 at 02:02
1

Since you'll only ever deal with two date formats, just check for a / or a - character.

import datetime

# M/D/Y
if '/' in datefield:
    final_date = datetime.datetime.strpdate(date, '%M/%D/%Y').isoformat()

# Y-M-D
elif '-' in datefield:
    final_date = datetime.datetime.strpdate(date, '%Y-%M-%D').isoformat()
Parker E.
  • 80
  • 7
0

A possible approach is to use the dateutil library. It contains many of the commonest datetime formats and can automagically detect these formats for you.

>>> from dateutil.parser import parse

>>> d1 = "12/29/2017"
>>> d2 = "2017-12-31"
>>> parse(d1)
datetime.datetime(2017, 12, 29, 0, 0)

>>> parse(d2)
datetime.datetime(2017, 12, 31, 0, 0)

NOTE: dateutil is a 3rd party library so you may need to install it with something like:

pip install python-dateutil

It can be found on pypi: https://pypi.python.org/pypi/python-dateutil/2.6.1

And works with Python2 and Python3.

Alternate Examples:

Here are a couple of alternate examples of how well dateutil handles random date formats:

>>> d3 = "December 28th, 2017"
>>> parse(d3)
datetime.datetime(2017, 12, 28, 0, 0)

>>> d4 = "27th Dec, 2017"
>>> parse(d4)
datetime.datetime(2017, 12, 27, 0, 0)
E. Ducateme
  • 4,028
  • 2
  • 20
  • 30
  • This would work too, but I want to avoid 3rd party libraries for the time being. If things get more complex, I might head down that road. – Cale Sweeney Dec 29 '17 at 21:24
0

I went with the advice of @ChristianDean and used the try-except block in effort to be Pythonic. The first format %m/%d/%Y appears a bit more in my data, so I lead the try-except with that datetime formatting attempt.

Here is my final solution:

import datetime
try: 
    final_date = datetime.datetime.strptime(datefield, "%m/%d/%Y").strftime("%Y-%m-%d")
except ValueError:
    final_date = datetime.datetime.strptime(datefield, "%Y-%m-%d").strftime("%Y-%m-%d")
Cale Sweeney
  • 1,014
  • 1
  • 15
  • 37