使用parsedatetime库,能否将日期限制为当前年份?
我想用 parsedatetime 这个工具,把像 Jan 1
这样的值传给日历解析器,希望它能返回当前年份的1月1日(比如现在发这个帖子时,就是 2014-01-01
)。
不过,默认情况下,parsedatetime 返回的是这个日期的下一个出现时间(也就是 2015-01-01
):
>>> import parsedatetime as pdt
>>> from datetime import datetime
>>> from time import mktime
>>> cal = pdt.Calendar()
>>> datetime.now()
datetime.datetime(2014, 8, 1, 15, 41, 7, 486294)
>>> str(datetime.fromtimestamp(mktime(cal.parse('Jan 1')[0])))
'2015-01-01 14:41:13'
>>> str(datetime.fromtimestamp(mktime(cal.parse('Dec 31')[0])))
'2014-12-31 14:41:17'
我试过输入像 last Jan 1
和 Jan 1 this year
,但是都没有成功。
有没有办法让解析器返回当前年份的值呢?
我补充一下原问题中没有提到的几个要求:
- 支持自然语言处理(这就是我使用 parsedatetime 的原因)
- 不影响 parsedatetime 的其他解析功能(比如处理当前年份以外的年份,以及像
yesterday
和6 months before 3/1
这样的值)
6 个回答
0
如果你不一定要使用那个库(也许你是吗?),你可以这样做:
>>> import datetime
>>> datetime.datetime.now().replace(month=1, day=1).strftime("%Y-%m-%d %H:%M:%S")
'2014-01-01 22:55:56'
>>>
0
这是一个基于Bear的回答改进的实现。
需要注意的是,由于这个实现是在另一个DSL解析器中进行的,natural_date
只能接受一个字符串:
import parsedatetime as pdt
from datetime import datetime, date, timedelta
from time import mktime
def natural_date(human_readable):
human_readable = human_readable.lower()
# Flag to cause parsedatetime to never go forward
# https://stackoverflow.com/a/25098991/1093087
ptc = pdt.Constants()
ptc.YearParseStyle = 0
cal = pdt.Calendar(ptc)
result, parsed_as = cal.parse(human_readable)
if not parsed_as:
raise ValueError("Unable to parse %s" % (human_readable))
return date.fromtimestamp(mktime(result))
def test_natural_date():
cases = [
# input, expect
('jan 1', date(date.today().year, 1, 1)),
('dec 31', date(date.today().year, 12, 31)),
('yesterday', date.today() - timedelta(days=1)),
('3 months before 12/31', date(date.today().year, 9, 30))
]
for human_readable, expect in cases:
result = natural_date(human_readable)
print("%s -> %s" % (human_readable, result))
assert result == expect, human_readable
test_natural_date()
同时也要感谢Mark Ransom,他发现了sourceTime
参数,这为解决这个问题提供了另一种方法,尽管这个解决方案受到这个问题的影响,变得有些复杂。
1
我建议你把你的日期时间对象中的年份替换掉。例如:
str(datetime.fromtimestamp(mktime(cal.parse('Dec 31')[0])))
就会变成:
str(datetime.fromtimestamp(mktime(cal.parse('Dec 31')[0])).replace(year=datetime.today().year))
3
这里是Bear - 我不知道怎么才能找回我原来的Stack Overflow个人资料,因为我以前用的是ClaimID...
不过,你可以设置一个标志,让parsedatetime在只解析月份和日期的时候,永远不会往前推一年...
import parsedatetime as pdt
ptc = pdt.Constants()
ptc.YearParseStyle = 0
cal = pdt.Calendar(ptc)
print cal.parse('Jan 1')
# ((2014, 1, 1, 15, 57, 32, 5, 214, 1), 1)
2
parse
函数似乎需要一个叫 sourceTime
的参数,你可以把它设置为当前年的第一天。
可以查看这个链接了解更多信息:https://bear.im/code/parsedatetime/docs/index.html