Date/Time Conversion
This utility class will convert different date time formats into the proper format to create a Python datetime object. It will use the current locate to determine differences that can not be determined in any other way such as 01/01/2010 meaning either dd/mm/yyyy or mm/dd/yyyy.
The methods are all classmethods.
A string value is passed into the DateUtils.toDatetime() method. If you know the format of your date or only want to allow a specific format that format can be passed into the format keyword argument.
Examples:
- - Date but no time
from dateutils import DateUtils
DateUtils.toDatetime('2010/04/05')
Out[2]: datetime.datetime(2010, 4, 5, 0, 0)- - Date and Time
from dateutils import DateUtils
DateUtils.toDatetime('2010/04/05 23:20:59')
Out[3]: datetime.datetime(2010, 4, 5, 23, 20, 59)- - Date, Time and the format is specified.
from dateutils import DateUtils
DateUtils.toDatetime('20100405232059', format="yyyymmddHHMMSS")
Out[6]: datetime.datetime(2010, 4, 5, 23, 20, 59)
Exceptions
A ValueError will be raised if the value does not match the format or if the format can not be determined.
A KeyError will be raised if the the date time format is not supported.
#
# dateutils.py
#
import re, locale
from datetime import datetime
class DateUtils(object):
__DATE_REGEX = r"[/.]+"
__dateRegex = re.compile(__DATE_REGEX)
__YMD = "yyyy-mm-dd hh:mm:ss"
__MDY = "mm-dd-yyyy hh:mm:ss"
__DMY = "dd-mm-yyyy hh:mm:ss"
__YMD_NON_DLM = "yyyymmddHHMMSS"
def __transposeFromYMDHMS(self, value):
size = len(value)
y = value[:4]
m = value[5:7]
d = value[8:10]
H = M = S = 0
if size >= 13: H = value[11:13]
if size >= 16: M = value[14:16]
if size >= 19: S = value[17:]
return "%s-%s-%s %02i:%02i:%02i" % (y, m, d, H, M, S)
def __transposeFromMDYHMS(self, value):
size = len(value)
m = value[:2]
d = value[3:5]
y = value[6:10]
H = M = S = 0
if size >= 13: H = value[11:13]
if size >= 16: M = value[14:16]
if size >= 19: S = value[17:]
return "%s-%s-%s %02i:%02i:%02i" % (y, m, d, H, M, S)
def __transposeFromDMYHMS(self, value):
size = len(value)
d = value[:2]
m = value[3:5]
y = value[6:10]
H = M = S = 0
if size >= 13: H = value[11:13]
if size >= 16: M = value[14:16]
if size >= 19: S = value[17:]
return "%s-%s-%s %02i:%02i:%02i" % (y, m, d, H, M, S)
def __transposeNonDelimiterYMDHMS(self, value):
size = len(value)
y = value[:4]
m = value[4:6]
d = value[6:8]
H = M = S = 0
if size >= 10: H = value[8:10]
if size >= 12: M = value[10:12]
if size >= 14: S = value[12:]
return "%s-%s-%s %02i:%02i:%02i" % (y, m, d, H, M, S)
__FROM_DATE_FORMATS = {__YMD: __transposeFromYMDHMS,
__MDY: __transposeFromMDYHMS,
__DMY: __transposeFromDMYHMS,
__YMD_NON_DLM: __transposeNonDelimiterYMDHMS}
@classmethod
def toDatetime(self, value, format=None):
"""
Convert a string representation of a date and time to a python
datetime object.
@param value: The string value to convert.
@keyword format: The format to convert from.
@return: A Python datetime object.
"""
if format is None: format = DateUtils._snoopDateFormat(value)
fmt = self.__dateRegex.sub('-', format)
try:
value = self.__FROM_DATE_FORMATS[fmt](self, value)
date, time = value.split(' ')
except KeyError, e:
msg = "Invalid date format should be one of %s."
raise KeyError(msg % self.__FROM_DATE_FORMATS.keys())
except ValueError, e:
msg = "The value %s does not match the format %s, %s"
raise ValueError(msg % (value, format, e))
try:
return datetime(*[int(float(x)) for x in date.split("-")] +
[int(float(x)) for x in time.split(":")])
except Exception, e:
msg = "Invalid format for datetime %s, found: %s, %s" % \
(fmt, value, e)
raise Exception(msg)
@classmethod
def _snoopDateFormat(self, value):
"""
We determine what we can then rely on the current systems locale
setting to determine the difference of 01/01/2010 to mean mm/dd/yyy
or dd/mm/yyyy.
"""
fmt = None
delim = any([char for char in value if char in ('-', '.', '/', ':')])
year = value[:4].isdigit()
lfmt = locale.nl_langinfo(locale.D_FMT)
if year and not delim:
fmt = self.__YMD_NON_DLM
elif year and delim:
fmt = self.__YMD
elif lfmt[1] == 'm':
fmt = self.__MDY
elif lfmt[1] == 'd':
fmt = self.__DMY
else:
msg = "Invalid date time format: %s"
raise ValueError(msg % value)
return fmt