Here is my take on this:
Go from fuzzy date to datetime object (which will fit into a database)
import datetime import iso8601 def fuzzy_to_datetime(fuzzy): flen = len(fuzzy) if flen == 4 and fuzzy.isdigit(): dt = datetime.datetime(year=int(fuzzy), month=1, day=1, microsecond=111111) elif flen == 7: y, m = fuzzy.split('-') dt = datetime.datetime(year=int(y), month=int(m), day=1, microsecond=222222) elif flen == 10: y, m, d = fuzzy.split('-') dt = datetime.datetime(year=int(y), month=int(m), day=int(d), microsecond=333333) elif flen >= 19: dt = iso8601.parse_date(fuzzy) else: raise ValueError("Unable to parse fuzzy date: %s" % fuzzy) return dt And then a function that takes the datetime object, and moves it back into a fuzzy date.
def datetime_to_fuzzy(dt): ms = str(dt.microsecond) flag1 = ms == '111111' flag2 = ms == '222222' flag3 = ms == '333333' is_first = dt.day == 1 is_jan1 = dt.month == 1 and is_first if flag1 and is_jan1: return str(dt.year) if flag2 and is_first: return dt.strftime("%Y-%m") if flag3: return dt.strftime("%Y-%m-%d") return dt.isoformat() And then a unit test. Did I miss any cases?
if __name__ == '__main__': assert fuzzy_to_datetime('2001').isoformat() == '2001-01-01T00:00:00.111111' assert fuzzy_to_datetime('1981-05').isoformat() == '1981-05-01T00:00:00.222222' assert fuzzy_to_datetime('2012-02-04').isoformat() == '2012-02-04T00:00:00.333333' assert fuzzy_to_datetime('2010-11-11T03:12:03Z').isoformat() == '2010-11-11T03:12:03+00:00' exact = datetime.datetime(year=2001, month=1, day=1, microsecond=231) assert datetime_to_fuzzy(exact) == exact.isoformat() assert datetime_to_fuzzy(datetime.datetime(year=2001, month=1, day=1, microsecond=111111)) == '2001' assert datetime_to_fuzzy(datetime.datetime(year=2001, month=3, day=1, microsecond=222222)) == '2001-03' assert datetime_to_fuzzy(datetime.datetime(year=2001, month=6, day=6, microsecond=333333)) == '2001-06-06' assert datetime_to_fuzzy(fuzzy_to_datetime('2002')) == '2002' assert datetime_to_fuzzy(fuzzy_to_datetime('2002-05')) == '2002-05' assert datetime_to_fuzzy(fuzzy_to_datetime('2002-02-13')) == '2002-02-13' assert datetime_to_fuzzy(fuzzy_to_datetime('2010-11-11T03:12:03.293856+00:00')) == '2010-11-11T03:12:03.293856+00:00' There is a corner case where an event that precisely occurred at 2001-01-01T00:00:00.333333 but the system will interpret as being just "2001", but that seems very unlikely.