What's the best way to make a time from “Today

2020-05-27 05:17发布

问题:

Python has pretty good date parsing but is the only way to recognize a datetime such as "Today 3:20 PM" or "Yesterday 11:06 AM" by creating a new date today and doing subtractions?

回答1:

A library that I like a lot, and I'm seeing more and more people use, is python-dateutil but unfortunately neither it nor the other traditional big datetime parser, mxDateTime from Egenix can parse the word "tomorrow" in spite of both libraries having very strong "fuzzy" parsers.

The only library I've seen that can do this is magicdate. Examples:

>>> import magicdate
>>> magicdate.magicdate('today')
datetime.date(2009, 2, 15)
>>> magicdate.magicdate('tomorrow')
datetime.date(2009, 2, 16)
>>> magicdate.magicdate('yesterday')
datetime.date(2009, 2, 14)

Unfortunately this only returns datetime.date objects, and so won't include time parts and can't handle your example of "Today 3:20 PM".

So, you need mxDateTime for that. Examples:

>>> import mx.DateTime

>>> mx.DateTime.Parser.DateTimeFromString("Today 3:20 PM")
<mx.DateTime.DateTime object for '2009-02-15 15:20:00.00' at 28faa28>

>>> mx.DateTime.Parser.DateTimeFromString("Tomorrow 5:50 PM")
<mx.DateTime.DateTime object for '2009-02-15 17:50:00.00' at 2a86088>

EDIT: mxDateTime.Parser is only parsing the time in these examples and ignoring the words "today" and "tomorrow". So for this particular case you need to use a combo of magicdate to get the date and mxDateTime to get the time. My recommendation is to just use python-dateutils or mxDateTime and only accept the string formats they can parse.


EDIT 2: As noted in the comments it looks python-dateutil can now handle fuzzy parsing. I've also since discovered the parsedatetime module that was developed for use in Chandler and it works with the queries in this question:

>>> import parsedatetime.parsedatetime as pdt
>>> import parsedatetime.parsedatetime_consts as pdc
>>> c=pdc.Constants()
>>> p=pdt.Calendar(c)
>>> p.parse('Today 3:20 PM')
((2010, 3, 12, 15, 20, 0, 4, 71, -1), 3)
>>> p.parse('Yesterday 11:06 AM')
((2010, 3, 11, 11, 6, 0, 3, 70, -1), 3)

and for reference here is the current time:

>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2010, 3, 12, 15, 23, 35, 951652)


回答2:

I am not yet completely up to speed on Python yet, but your question interested me, so I dug around a bit.

Date subtraction using timedelta is by far the most common solution I found.

Since your question asks if that's the only way to do it, I checked out the strftime format codes to see if you could define your own. Unfortunately not. From Python's strftime documentation:

... The full set of format codes supported varies across platforms, because Python calls the platform C library’s strftime() function, and platform variations are common.

The following is a list of all the format codes that the C standard (1989 version) requires ...

Anyhow, this isn't a definitive answer, but maybe It'll save others time barking up the wrong tree.