什么是最优雅的方式来结束一天(日期时间)?

时间:2011-11-02 18:50:14

标签: python

更新:我已在此问题的底部添加了解决方案。

我目前正在编写一些报告代码,允许用户选择指定日期范围。它的工作方式(简化)是:

  • 用户(可选)指定年份。
  • 用户(可选)指定月份。
  • 用户(可选)指定一天。

以下是代码段,以及描述我喜欢的内容的评论:

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 =今晚),那样我们默认只在当天做一些事情。

感谢大家的回答 - 他们对我的研究很有帮助。

6 个答案:

答案 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 =今晚)我们将默认仅在当天进行操作。

感谢大家的回答-他们对我的研究很有帮助。