title: How to pandas.date_range() to generate a range with no timestamps posterior to end parameter?
body: <p>I'm working in python with pandas. I'm querying an external data source for unique users over a group of days (eg unique users per 30 days or per 2 days or per 7 days). The query needs a period start, a period end and an interval ( number of days).</p>
  
  <p>For example to get unique users for jan 1st the params are :</p>
  
  <ul>
  <li>start: 2015-01-01</li>
  <li>end: 2015-01-01</li>
  <li>interval: 1</li>
  </ul>
  
  <p>For jan 1st to jan 3rd inclusively (3 days grouped):</p>
  
  <ul>
  <li>start: 2015-01-01</li>
  <li>end: 2015-01-03</li>
  <li>interval: 3</li>
  </ul>
  
  <p>Sometimes I also need multiple periods. in all cases a period can finish beyond the end date, but never start after the end.</p>
  
  <p>For example 30 days uniques for jan 1st to jan 1st:</p>
  
  <ul>
  <li>start: 2015-01-01</li>
  <li>end: 2015-01-01</li>
  <li>interval: 30</li>
  </ul>
  
  <p>Ideally I would have used <code>pandas.period_range()</code>, but since it doesn't accept multiple in the <code>freq</code> parameter, I turned to <code>pandas.date_range()</code>. I'm iterating over the timestamps in the date range like so:</p>
  
  <pre><code>import pandas
  start_date = "2015-01-01"
  end_date = "2015-01-03"
  interval = 3
  
  for timestamp in pandas.date_range(start_date , end_date , freq=str(interval)+"D"):
      period_start = timesteamp.date()
      period_end = period_start + datetime.timedelta(days=interval)
      # query with period_start, period_end, interval
  </code></pre>
  
  <p>So when the last element of the range generated by pandas is after the end parameter it produce an unnecessary loop and unwanted query that I want to avoid.</p>
  
  <p>The problem is calls like this:</p>
  
  <pre><code>pandas.date_range("2015-01-01", "2015-01-03", freq="3D")
  </code></pre>
  
  <p>return:</p>
  
  <pre><code>&lt;class 'pandas.tseries.index.DatetimeIndex'&gt;
  [2015-01-01, 2015-01-04]
  Length: 2, Freq: 3D, Timezone: None
  </code></pre>
  
  <p>With the last element 2015-01-04 being posterior to the end limit 2015-01-03. This doesn't happen when the frequency is shorter or longer than the actual period (in this case 2 days or 4 days):</p>
  
  <pre><code>&gt;&gt;&gt; pandas.date_range("2015-01-01", "2015-01-03", freq="2D")
  &lt;class 'pandas.tseries.index.DatetimeIndex'&gt;
  [2015-01-01, 2015-01-03]
  Length: 2, Freq: 2D, Timezone: None
  
  &gt;&gt;&gt; pandas.date_range("2015-01-01", "2015-01-03", freq="4D")
  &lt;class 'pandas.tseries.index.DatetimeIndex'&gt;
  [2015-01-01]
  Length: 1, Freq: 4D, Timezone: None
  </code></pre>
  
  <p>I tried to understand the close parameter but the description is a bit cryptic for me. None of the three values ("right", "left", None) seem to give what I'm after.</p>
  
  <p>I tested the 3 possible <code>closed=</code> values to observe the different outputs:</p>
  
  <pre><code>&gt;&gt;&gt; pandas.date_range("2015-01-01", "2015-01-03", freq="3D", closed="left")
  &lt;class 'pandas.tseries.index.DatetimeIndex'&gt;
  [2015-01-01]
  Length: 1, Freq: 3D, Timezone: None
  </code></pre>
  
  <p>This seems like the desired result. But in the case where the <code>freq</code> is longer than the time between start and end, it returns a range with 0 elements.</p>
  
  <pre><code>&gt;&gt;&gt; pandas.date_range("2015-01-01", "2015-01-01", freq="10D", closed="left")
  &lt;class 'pandas.tseries.index.DatetimeIndex'&gt;
  Length: 0, Freq: 10D, Timezone: None
  </code></pre>
  
  <p>I'd expect :</p>
  
  <pre><code>&lt;class 'pandas.tseries.index.DatetimeIndex'&gt;
  [2015-01-01]
  Length: 1, Freq: 10D, Timezone: None
  </code></pre>
  
  <p>The only time I would see the result being empty is if the <code>freq</code> has a multiplier of 0 (ie "0D", "0H", "0W"). This already raises an error, so in <code>practice date_range()</code> should always return at least it's start value. If the end parameter occurs earlier than the end of the frequency, then the range would only contain one timestamp.</p>