python获取天 - time time单位




在Python中遍历一系列日期 (10)

我有下面的代码来做到这一点,但我怎么能做得更好? 现在我认为它比嵌套循环更好,但是当你在列表理解中有一个生成器时,它开始获得Perl-一个标准。

day_count = (end_date - start_date).days + 1
for single_date in [d for d in (start_date + timedelta(n) for n in range(day_count)) if d <= end_date]:
    print strftime("%Y-%m-%d", single_date.timetuple())

笔记

  • 我实际上没有使用它来打印。 这只是为了演示目的。
  • start_dateend_date变量是datetime.date对象,因为我不需要时间戳。 (他们将用于生成报告)。

示例输出

对于2009-05-30的开始日期和2009-06-09的结束日期:

2009-05-30
2009-05-31
2009-06-01
2009-06-02
2009-06-03
2009-06-04
2009-06-05
2009-06-06
2009-06-07
2009-06-08
2009-06-09

Numpy的arange函数可以应用于日期:

import numpy as np
from datetime import datetime, timedelta
d0 = datetime(2009, 1,1)
d1 = datetime(2010, 1,1)
dt = timedelta(days = 1)
dates = np.arange(d0, d1, dt).astype(datetime)

astype的使用是将numpy.datetime64转换为datetime.datetime对象的数组。


显示从今天起的最后n天:

import datetime
for i in range(0, 100):
    print((datetime.date.today() + datetime.timedelta(i)).isoformat())

输出:

2016-06-29
2016-06-30
2016-07-01
2016-07-02
2016-07-03
2016-07-04

为什么不尝试:

import datetime as dt

start_date = dt.datetime(2012, 12,1)
end_date = dt.datetime(2012, 12,5)

total_days = (end_date - start_date).days + 1 #inclusive 5 days

for day_number in range(total_days):
    current_date = (start_date + dt.timedelta(days = day_number)).date()
    print current_date

为什么有两个嵌套迭代? 对我来说,它只产生一次迭代的相同数据列表:

for single_date in (start_date + timedelta(n) for n in range(day_count)):
    print ...

没有列表被存储,只有一个生成器被迭代。 此外,发电机中的“如果”似乎是不必要的。

毕竟,线性序列应该只需要一个迭代器,而不是两个。

与John Machin讨论后更新:

也许最优雅的解决方案是使用生成器函数来完全隐藏/抽象日期范围内的迭代:

from datetime import timedelta, date

def daterange(start_date, end_date):
    for n in range(int ((end_date - start_date).days)):
        yield start_date + timedelta(n)

start_date = date(2013, 1, 1)
end_date = date(2015, 6, 2)
for single_date in daterange(start_date, end_date):
    print single_date.strftime("%Y-%m-%d")

注意:为了与内置的range()函数保持一致,这个迭代到达end_date 之前停止。 因此,对于包含迭代使用第二天,就像使用range()


使用dateutil库:

from datetime import date
from dateutil.rrule import rrule, DAILY

a = date(2009, 5, 30)
b = date(2009, 6, 9)

for dt in rrule(DAILY, dtstart=a, until=b):
    print dt.strftime("%Y-%m-%d")

这个python库有许多更高级的功能,一些非常有用,比如relative delta s,并且被实现为一个单独的文件(模块),很容易包含到项目中。


如何做一个范围增加几天:

for d in map( lambda x: startDate+datetime.timedelta(days=x), xrange( (stopDate-startDate).days ) ):
  # Do stuff here
  • startDate和stopDate是datetime.date对象

对于通用版本:

for d in map( lambda x: startTime+x*stepTime, xrange( (stopTime-startTime).total_seconds() / stepTime.total_seconds() ) ):
  # Do stuff here
  • startTime和stopTime是datetime.date或datetime.datetime对象(两者应该是相同的类型)
  • stepTime是一个timedelta对象

请注意,.total_seconds()仅在python 2.7之后受支持。如果您遇到较早的版本,您可以编写自己的函数:

def total_seconds( td ):
  return float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

这个功能有一些额外的功能:

  • 可以传递匹配DATE_FORMAT的字符串作为开始或结束,并将其转换为日期对象
  • 可以传递一个开始或结束的日期对象
  • 错误检查以防止结束比起始更早

    import datetime
    from datetime import timedelta
    
    
    DATE_FORMAT = '%Y/%m/%d'
    
    def daterange(start, end):
          def convert(date):
                try:
                      date = datetime.datetime.strptime(date, DATE_FORMAT)
                      return date.date()
                except TypeError:
                      return date
    
          def get_date(n):
                return datetime.datetime.strftime(convert(start) + timedelta(days=n), DATE_FORMAT)
    
          days = (convert(end) - convert(start)).days
          if days <= 0:
                raise ValueError('The start date must be before the end date.')
          for n in range(0, days):
                yield get_date(n)
    
    
    start = '2014/12/1'
    end = '2014/12/31'
    print list(daterange(start, end))
    
    start_ = datetime.date.today()
    end = '2015/12/1'
    print list(daterange(start, end))
    

这可能会更清楚:

d = start_date
delta = datetime.timedelta(days=1)
while d <= end_date:
    print d.strftime("%Y-%m-%d")
    d += delta

for i in range(16):
    print datetime.date.today() + datetime.timedelta(days=i)

import datetime

def daterange(start, stop, step=datetime.timedelta(days=1), inclusive=False):
  # inclusive=False to behave like range by default
  if step.days > 0:
    while start < stop:
      yield start
      start = start + step
      # not +=! don't modify object passed in if it's mutable
      # since this function is not restricted to
      # only types from datetime module
  elif step.days < 0:
    while start > stop:
      yield start
      start = start + step
  if inclusive and start == stop:
    yield start

# ...

for date in daterange(start_date, end_date, inclusive=True):
  print strftime("%Y-%m-%d", date.timetuple())

这个函数的功能超出了你的严格要求,支持负面步骤等等。只要你将范围逻辑分解出来,那么你不需要单独的day_count ,最重要的是,当你调用函数时,代码变得更容易阅读多个地方。







iteration