Iterating through a range of dates in Python

后端 未结 23 1352
醉酒成梦
醉酒成梦 2020-11-22 04:40

I have the following code to do this, but how can I do it better? Right now I think it\'s better than nested loops, but it starts to get Perl-one-linerish when you have a ge

相关标签:
23条回答
  • 2020-11-22 04:46
    import datetime
    
    def daterange(start, stop, step_days=1):
        current = start
        step = datetime.timedelta(step_days)
        if step_days > 0:
            while current < stop:
                yield current
                current += step
        elif step_days < 0:
            while current > stop:
                yield current
                current += step
        else:
            raise ValueError("daterange() step_days argument must not be zero")
    
    if __name__ == "__main__":
        from pprint import pprint as pp
        lo = datetime.date(2008, 12, 27)
        hi = datetime.date(2009, 1, 5)
        pp(list(daterange(lo, hi)))
        pp(list(daterange(hi, lo, -1)))
        pp(list(daterange(lo, hi, 7)))
        pp(list(daterange(hi, lo, -7))) 
        assert not list(daterange(lo, hi, -1))
        assert not list(daterange(hi, lo))
        assert not list(daterange(lo, hi, -7))
        assert not list(daterange(hi, lo, 7)) 
    
    0 讨论(0)
  • 2020-11-22 04:47

    Pandas is great for time series in general, and has direct support for date ranges.

    import pandas as pd
    daterange = pd.date_range(start_date, end_date)
    

    You can then loop over the daterange to print the date:

    for single_date in daterange:
        print (single_date.strftime("%Y-%m-%d"))
    

    It also has lots of options to make life easier. For example if you only wanted weekdays, you would just swap in bdate_range. See http://pandas.pydata.org/pandas-docs/stable/timeseries.html#generating-ranges-of-timestamps

    The power of Pandas is really its dataframes, which support vectorized operations (much like numpy) that make operations across large quantities of data very fast and easy.

    EDIT: You could also completely skip the for loop and just print it directly, which is easier and more efficient:

    print(daterange)
    
    0 讨论(0)
  • 2020-11-22 04:48
    for i in range(16):
        print datetime.date.today() + datetime.timedelta(days=i)
    
    0 讨论(0)
  • 2020-11-22 04:52
    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())
    

    This function does more than you strictly require, by supporting negative step, etc. As long as you factor out your range logic, then you don't need the separate day_count and most importantly the code becomes easier to read as you call the function from multiple places.

    0 讨论(0)
  • 2020-11-22 04:56

    Use the dateutil library:

    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")
    

    This python library has many more advanced features, some very useful, like relative deltas—and is implemented as a single file (module) that's easily included into a project.

    0 讨论(0)
  • 2020-11-22 04:56

    This function has some extra features:

    • can pass a string matching the DATE_FORMAT for start or end and it is converted to a date object
    • can pass a date object for start or end
    • error checking in case the end is older than the start

      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))
      
    0 讨论(0)
提交回复
热议问题