Charon February 2016

Inclusive date ranges in python

I didn't phrase this question correctly and as a result, none of the answers quite hit the mark.

What I wanted to know is, what's the best way to get time to return the end of a day in epoch milliseconds, if given just the date, rather than both date and time?

Here's how I'm doing it at the moment:

def get_epoch_endofday(day):
    return time.mktime(time.strptime('005923'+day,"%S%M%H%d%m%y"))*1000

The function takes the date in the form ddmmyy, and then spits out the epoch milliseconds on that day at 23:59:00.

I wondered, is there a more elegant way of doing this?

Answers


Genti Saliu February 2016

It wasn't very clear at first, but you want to create an interval for a given day (say 2016-02-14), which contains the first and last instant of that day. That means:

First instant: 2016-02-14 00:00:00.000

Last instant: 2016-02-14 23:59:59.999

The function below returns that interval as a tupel. It works like this:

  • create the start of the interval by creating a new date instance on the same day with hours, minutes and milliseconds all set to 0
  • create an interval spanning 23 hours, 59 minutes, 59 seconds and 999999 microseconds
  • add this interval to the beginning of the day

Code:

from datetime import datetime, timedelta

# 2016-02-08 11:39:31.093209
day = datetime.now()

def get_day_interval(day):
    start = datetime(day.year, day.month, day.day)
    interval = timedelta(seconds=59, microseconds=999999, minutes=59, hours=23)
    return (start, start + interval)

(start, end) = get_day_interval(day)

# 2016-02-08 00:00:00
print(start)

# 2016-02-08 23:59:59.999999
print(end)

Consult the Python docs for more options.

If the interval can be exclusive, the code becomes simpler, see the summary of this answer.


Pouria Hadjibagheri February 2016

Generators

Here is how you can create a function that produces an inclusive range:

def inc_range(stop, start=0, step=1):
    numerator = start

    while numerator<=stop:
        yield numerator
        numerator += step


a = [val for val in inc_range(10)]
print(a)

Displays:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Now this method can be adapted for anything you want; date or otherwise.

Date range generator

Here it the method tailored to your needs:

from datetime import date, timedelta 


def date_range(stop, start, step=1):
    delta_date = stop - start
    numerator = 0

    while numerator <= delta_date.days:
        yield str(start + timedelta(numerator))
        numerator += step


date_start = date(2014, 3, 15)
date_end = date(2014, 3, 21)

a = [val for val in date_range(date_end, date_start)]
print(a)

Displays:

['2014-03-15', '2014-03-16', '2014-03-17', '2014-03-18', '2014-03-19', '2014-03-20', '2014-03-21']

Note that if you don't include str() when yielding in the generator, the response would be an object of datetime.date() instead.

Hope this answers your question.

Post Status

Asked in February 2016
Viewed 1,772 times
Voted 8
Answered 2 times

Search




Leave an answer