djangodatetimetimehumanize

Reversing the result of Django's naturaltime


Django's humanize module is fantastic for turning datetime objects into something that makes more sense to us as humans with it's naturaltime function (docs). What I'm trying to do is the reverse, taking any one of the naturaltime formats and converting it back to a datetime (accepting the obvious loss of precision).

Is there any existing library to do this or am I going to have to write my own datetime.strptime patterns?

I know this is a bit of a "find me a tool/library" question, but I've googled around quite a bit with no results.


Solution

  • For any future searchers, I ended up writing dehumanize to handle this question. It's on github here.

    from datetime import datetime, timedelta
    import re
    
    
    def naturaltime(text, now=None):
        """Convert a django naturaltime string to a datetime object."""
        if not now:
            now = datetime.now()
    
        if text == 'now':
            return now
        if "ago" in text:
            multiplier = -1
        elif "from now" in text:
            multiplier = 1
        else:
            raise ValueError("%s is not a valid naturaltime" % text)
    
        text = text.replace('an ', '1 ')
        text = text.replace('a ', '1 ')
    
        days = get_first(r'(\d*) day', text)
        hours = get_first(r'(\d*) hour', text)
        minutes = get_first(r'(\d*) minute', text)
        seconds = get_first(r'(\d*) second', text)
        delta = timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds)
        delta *= multiplier
        return now + delta
    
    
    def get_first(pattern, text):
        """Return either a matched number or 0."""
        matches = re.findall(pattern, text)
        if matches:
            return int(matches[0])
        else:
            return 0