更新:我已在此问题的底部添加了解决方案。
我目前正在编写一些报告代码,允许用户选择指定日期范围。它的工作方式(简化)是:
以下是代码段,以及描述我喜欢的内容的评论:
from datetime import datetime, timedelta
# ...
now = datetime.now()
start_time = now.replace(hour=0, minute=0, second=0, microsecond=0)
stop_time = now
# If the user enters no year, month, or day--then we'll simply run a
# report that only spans the current day (from the start of today to now).
if options['year']:
start_time = start_time.replace(year=options['year'], month=0, day=0)
stop_time = stop_time.replace(year=options['year'])
# If the user specifies a year value, we should set stop_time to the last
# day / minute / hour / second / microsecond of the year, that way we'll
# only generate reports from the start of the specified year, to the end
# of the specified year.
if options['month']:
start_time = start_time.replace(month=options['month'], day=0)
stop_time = stop_time.replace(month=options['month'])
# If the user specifies a month value, then set stop_time to the last
# day / minute / hour / second / microsecond of the specified month, that
# way we'll only generate reports for the specified month.
if options['day']:
start_time = start_time.replace(day=options['day'])
stop_time = stop_time.replace(day=options['day'])
# If the user specifies a day value, then set stop_time to the last moment of
# the current day, so that reports ONLY run on the current day.
我正在努力找到最优雅的方式来编写上面的代码 - 我一直在试图找到一种方法来实现timedelta,但似乎无法弄明白。任何建议将不胜感激。
感谢。
编辑,添加解决方案:
在看完这里的一些答案后,并没有真正找到任何非常优雅的东西,我在标准库周围做了一些探索,找到了我当前的解决方案(我非常喜欢):dateutil。
以下是我实施它的方式:
from datetime import date
from dateutil.relativedelta import relativedelta
now = date.today()
stop_time = now + relativedelta(days=1)
start_time = date(
# NOTE: I'm not doing dict.get() since in my implementation, these dict
# keys are guaranteed to exist.
year = options['year'] or now.year,
month = options['month'] or now.month,
day = options['day'] or now.day
)
if options['year']:
start_time = date(year=options['year'] or now.year, month=1, day=1)
stop_time = start_time + relativedelta(years=1)
if options['month']:
start_time = date(
year = options['year'] or now.year,
month = options['month'] or now.month,
day = 1
)
stop_time = start_time + relativedelta(months=1)
if options['day']:
start_time = date(
year = options['year'] or now.year,
month = options['month'] or now.month,
day = options['day'] or now.day,
)
stop_time = start_time + relativedelta(days=1)
# ... do stuff with start_time and stop_time here ...
我喜欢这个实现,是python的dateutil.relativedata.relativedata在边缘情况下工作得非常好。它使得日/月/年正确无误。如果我有月份= 12,并且执行relativedata(月份= 1),它将增加年份并将月份设置为1(效果很好)。
另外:在上面的实现中,如果用户没有指定任何可选日期(年,月或日) - 我们将回退到一个不错的默认值(start_time =今天早上,stop_time =今晚),那样我们默认只在当天做一些事情。
感谢大家的回答 - 他们对我的研究很有帮助。
答案 0 :(得分:4)
使用dict.get
可以简化您的代码。它比使用 datetime.replace 和 timedelta 对象更清晰。
这是让你入门的东西:
from datetime import datetime
options = dict(month=5, day=20)
now = datetime.now()
start_time = datetime(year=options.get('year', now.year),
month=options.get('month', 1),
day=options.get('day', 1)
hour=0,
minute=0,
second=0)
stop_time = datetime(year=options.get('year', now.year),
month=options.get('month', now.month),
day=options.get('day', now.day),
hour=now.hour,
minute=now.minute,
second=now.second)
答案 1 :(得分:4)
根据需要设置stop_time
,提前start_time
一年,一月或一天,然后减去一个timedelta(microseconds=1)
if options['year']:
start_time = start_time.replace(year=options['year'], month=1, day=1)
stop_time = stop_time.replace(year=options['year']+1)-timedelta(microseconds=1)
elif options['month']:
start_time = start_time.replace(month=options['month'], day=1)
months=options['month']%12+1
stop_time = stop_time.replace(month=months,day=1)-timedelta(microseconds=1)
else:
start_time = start_time.replace(day=options['day'])
stop_time = stop_time.replace(day=options['day'])+timedelta(days=1,microseconds=-1)
答案 2 :(得分:1)
today = datetime.date.today()
begintime = today.strftime("%Y-%m-%d 00:00:00")
endtime = today.strftime("%Y-%m-%d 23:59:59")
答案 3 :(得分:0)
from datetime import datetime, date, timedelta
def get_current_timestamp():
return int(datetime.now().timestamp())
def get_end_today_timestamp():
# get 23:59:59
result = datetime.combine(date.today() + timedelta(days=1), datetime.min.time())
return int(result.timestamp()) - 1
def get_datetime_from_timestamp(timestamp):
return datetime.fromtimestamp(timestamp)
end_today = get_datetime_from_timestamp(get_end_today_timestamp())
答案 4 :(得分:0)
date = datetime.strftime('<input date str>')
date.replace(hour=0, minute=0, second=0, microsecond=0) # now we get begin of the day
date += timedelta(days=1, microseconds=-1) # now end of the day
答案 5 :(得分:0)
在查看了这里的一些答案之后,并没有真正找到任何非常优雅的方法,我在标准库中进行了一些探索,找到了当前的解决方案(我非常喜欢):dateutil
。
这是我的实现方式:
from datetime import date
from dateutil.relativedelta import relativedelta
now = date.today()
stop_time = now + relativedelta(days=1)
start_time = date(
# NOTE: I'm not doing dict.get() since in my implementation, these dict
# keys are guaranteed to exist.
year = options['year'] or now.year,
month = options['month'] or now.month,
day = options['day'] or now.day
)
if options['year']:
start_time = date(year=options['year'] or now.year, month=1, day=1)
stop_time = start_time + relativedelta(years=1)
if options['month']:
start_time = date(
year = options['year'] or now.year,
month = options['month'] or now.month,
day = 1
)
stop_time = start_time + relativedelta(months=1)
if options['day']:
start_time = date(
year = options['year'] or now.year,
month = options['month'] or now.month,
day = options['day'] or now.day,
)
stop_time = start_time + relativedelta(days=1)
# ... do stuff with start_time and stop_time here ...
我喜欢这种实现方式,是python的dateutil.relativedata.relativedata
在边缘情况下确实能很好地工作。它得到正确的天/月/年。如果我有month=12
,并且做relativedata(months=1)
,它将增加年份并将月份设置为1(效果很好)。
也:在上述实现中,如果用户未指定任何可选日期(年,月或日),则我们将使用备用默认日期(start_time =今天上午,stop_time =今晚)我们将默认仅在当天进行操作。
感谢大家的回答-他们对我的研究很有帮助。