I have two datetime objects, let's say start_date and end_date. What I want to do is to make a list of datetime objects.
>>> from datetime import datetime
>>> from dateutil.rrule import rrule, MONTHLY
>>> start_date = datetime(2018, 9, 6, 0,)
>>> end_date = datetime(2018, 11, 26, 23, 59, 59)
>>> list(rrule(MONTHLY, dtstart=start_date, until=end_date))
[datetime.datetime(2018, 9, 6, 0, 0), datetime.datetime(2018, 10, 6, 0, 0), datetime.datetime(2018, 11, 6, 0, 0)]
I can do this with rrule(), it's moving from date to date but I want it to go month-wise and also include the end_date,
[
datetime.datetime(2018,9,6,0,0),
datetime.datetime(2018,9,30,23,59),
datetime.datetime(2018,10,1,0,0),
datetime.datetime(2018,10,31,23,59),
datetime.datetime(2018,11,1,0,0),
datetime.datetime(2018,11,26,23,59)
]
I would prefer to do this without using pandas or numpy.
Try this
import datetime
def last_day_of_month(date):
if date.month == 12:
return date.replace(day=31)
return date.replace(month=date.month+1, day=1) - datetime.timedelta(days=1)
def desired_output(start_date,end_date):
curr_date = start_date
desired_list = []
desired_list.append(start_date)
while curr_date<=end_date:
if last_day_of_month(curr_date)>end_date:
desired_list.append(end_date)
break
desired_list.append(last_day_of_month(curr_date))
curr_date = last_day_of_month(curr_date) + datetime.timedelta(1)
if curr_date<end_date:
desired_list.append(curr_date)
else:
break
return desired_list
print(desired_output(datetime.datetime(2018,9,6,0,0), datetime.datetime(2018,12,26,0,0)))
here's how you can get a list of dates between two ranges. you can modify it to add certain dates.
from datetime import datetime
from datetime import timedelta
import calendar
dates = []
start_date = datetime(2018, 9, 6, 0,)
end_date = datetime(2018, 10, 10, 0,)
index_date = start_date
while True:
index_date = index_date
dates.append(index_date)
dayy = calendar.monthrange(index_date.year,index_date.month)
index_date = index_date.replace(day= dayy[1])
if index_date > end_date:
break
dates.append(index_date)
index_date = index_date + timedelta(days=1)
if index_date > end_date:
break
print dates
Related
I know this question is a repeated one. But what I am trying to do is, I want to iterate through a date range and for each iteration i need to set the fromDate and toDate.
for ex:
If I give the date range as startDate = '2022-10-31'
and endDate = '2022-11-04'
and for each iteration fromDate = '2022-10-31' and toDate = '2022-11-01'
next iteration fromDate = '2022-11-01' and endDate = '2022-11-02' and so on.
I did some research and got to know how to iterate through dateRange.
sample code:
import datetime
start_date = datetime.date(2022, 10, 31)
end_date = datetime.date(2022, 11, 04)
dates_2011_2013 = [ start_date + datetime.timedelta(n) for n in range(int ((end_date - start_date).days))]
This just prints the incremented dates in the date Range. Am new to Python language. Any help is appreciated.
Thank you.
You can change the code slightly to,
import datetime
start_date = datetime.date(2022, 10, 31)
end_date = datetime.date(2022, 11, 4)
dates_2011_2013 = [ (start_date + datetime.timedelta(n), start_date + datetime.timedelta(n+1)) for n in range(int ((end_date - start_date).days))]
[(datetime.date(2022, 10, 31), datetime.date(2022, 11, 1)),
(datetime.date(2022, 11, 1), datetime.date(2022, 11, 2)),
(datetime.date(2022, 11, 2), datetime.date(2022, 11, 3)),
(datetime.date(2022, 11, 3), datetime.date(2022, 11, 4))]
First item of the tuple is start date and the second item is end date.
I want to iterate through a date range
another option is using while:
while start_date < end_date:
print(start_date, start_date + datetime.timedelta(1))
start_date += datetime.timedelta(1)
'''
2022-10-31 2022-11-01
2022-11-01 2022-11-02
2022-11-02 2022-11-03
2022-11-03 2022-11-04
I am trying to subtract two dates or days from today's date. I want to get the result in years, months, days. How to do that?
Expecting 1 year, 2 months, 5 days, 20 days, 3 months, 2 days ago, etc. instead of just days.
import datetime
import pytz
tz='US/Pacific'
birthday = datetime.datetime(2020, 2, 19, 12, 0, 0)
>>> import datetime
>>> import pytz
>>> tz='US/Pacific'
>>> birthday = datetime.datetime(2020, 2, 19, 12, 0, 0)
>>> diff = datetime.datetime.now() - birthday
>>>
>>> diff
datetime.timedelta(days=326, seconds=39130, microseconds=319509)
>>>
>>> birthday = datetime.datetime(2015, 2, 19, 12, 0, 0)
>>> diff = datetime.datetime.now() - birthday
>>> diff
datetime.timedelta(days=2152, seconds=39151, microseconds=823846)
>>>
>>> diff.days
2152
Use dateutil.relativedelta from the dateutil package:
import datetime
from dateutil.relativedelta import relativedelta
>>> relativedelta(datetime.datetime.now(), datetime.datetime(2020, 2, 19, 12, 0, 0))
relativedelta(months=+10, days=+23, hours=+4, minutes=+8, seconds=+42, microseconds=+204978)
>>> relativedelta(datetime.datetime.now(), datetime.datetime(2015, 2, 19, 12, 0, 0))
relativedelta(years=+5, months=+10, days=+23, hours=+4, minutes=+9, seconds=+10, microseconds=+624971)
You can extract years, months, etc. like relativedelta().years, relativedelta().months, etc.
This answer may be helped you. But also you can check this using timetuple()
from datetime import datetime
import datetime
import pytz
tz = 'US/Pacific'
birthday = datetime.datetime(2020, 2, 19, 12, 0, 0)
b = birthday.timetuple()
n = datetime.datetime.now().timetuple()
print(f'Year diff: {n.tm_year-b.tm_year}')
print(f'Month diff: {n.tm_mon-b.tm_mon}')
print(f'Day diff: {n.tm_mday-b.tm_mday}')
I tried to exclude specific dates from a range of date and not getting valid output and below is the code. Could you please help to fix it.
from datetime import timedelta, date
sdate = date(2020, 7, 1)
edate = date(2020, 7, 7)
delta = edate - sdate
toRemoveDate = [date(2020, 7, 6), date(2020, 7, 2)]
for i in range(delta.days + 1):
day = sdate + timedelta(days=i)
print(day)
for j in range(len(toRemoveDate)):
if day != toRemoveDate[j]:
print(day)
Thanks,
Anand
try this,
from datetime import timedelta, date
sdate = date(2020, 7, 1)
edate = date(2020, 7, 7)
delta = edate - sdate
toRemoveDate = [date(2020, 7, 6), date(2020, 7, 2)]
for i in range(delta.days + 1):
day = sdate + timedelta(days=i)
if day not in toRemoveDate: # <-- check if day not in list
print(day)
Try .drop()
from datetime import timedelta, date
import pandas as pd
sdate = date(2020, 7, 1)
edate = date(2020, 7, 7)
range = pd.date_range(start=str(sdate), end=str(edate))
toRemoveDate = [date(2020, 7, 6), date(2020, 7, 2)]
days = range.drop(toRemoveDate)
print(days)
How would I create an rrule that excludes only the end timestamp using dateutil? Would I have to create a custom function or is there a way to do it natively?
here is an example
rule = rrule.rrule(rule.HOURLY,tsstart=somedate,until=somedate_four_hours_later)
I want the output to EXCLUDE somedate_four_hours_later and only generate 4 timestamps, somedate, somedate+1 hour, etc.
One way to do this is to use an rruleset, which allows you to combine recurrence rules and specific dates as required. In this case, what you'd do is set the until date as an exdate (excluded date):
from dateutil import rrule
from datetime import datetime, timedelta
dtstart = datetime(2015, 1, 3, 12)
dtuntil = datetime(2015, 1, 3, 16)
rr = rrule.rrule(freq=rrule.HOURLY, dtstart=dtstart, until=dtuntil)
# Add your rrule to the ruleset, then exclude the until date from the rule set
rrset = rrule.rruleset()
rrset.rrule(rr)
l1 = list(rrset)
rrset.exdate(dtuntil)
l2 = list(rrset)
print(l1[-1]) # 2015-01-03 16:00:00
print(l2[-1]) # 2015-01-03 15:00:00
The rrule itself will include the until date, but the exdate will exclude it from the rruleset.
You can set the count:
In [1]: from dateutil import rrule
In [2]: from datetime import datetime, timedelta
In [3]: st = datetime(2016, 7, 5, 23, 30)
In [4]: rule = rrule.rrule(rrule.HOURLY, st, count=4)
In [5]: print(list(rule))
[datetime.datetime(2016, 7, 5, 23, 30), datetime.datetime(2016, 7, 6, 0, 30), datetime.datetime(2016, 7, 6, 1, 30), datetime.datetime(2016, 7, 6, 2, 30)]
Or use timedelta adding three hours to the start:
from datetime import datetime, timedelta
st = datetime(2016, 7, 5, 23, 30)
rule = rrule.rrule(rrule.HOURLY, st, until=(st + timedelta(hours=3)))
I'm looking for an elegant and pythonic way to get the date of the end of the previous quarter.
Something like this:
def previous_quarter(reference_date):
...
>>> previous_quarter(datetime.date(2013, 5, 31))
datetime.date(2013, 3, 31)
>>> previous_quarter(datetime.date(2013, 2, 1))
datetime.date(2012, 12, 31)
>>> previous_quarter(datetime.date(2013, 3, 31))
datetime.date(2012, 12, 31)
>>> previous_quarter(datetime.date(2013, 11, 1))
datetime.date(2013, 9, 30)
Edit: Have I tried anything?
Yes, this seems to work:
def previous_quarter(ref_date):
current_date = ref_date - timedelta(days=1)
while current_date.month % 3:
current_date -= timedelta(days=1)
return current_date
But it seems unnecessarily iterative.
You can do it the "hard way" by just looking at the month you receive:
def previous_quarter(ref):
if ref.month < 4:
return datetime.date(ref.year - 1, 12, 31)
elif ref.month < 7:
return datetime.date(ref.year, 3, 31)
elif ref.month < 10:
return datetime.date(ref.year, 6, 30)
return datetime.date(ref.year, 9, 30)
Using dateutil:
import datetime as DT
import dateutil.rrule as rrule
def previous_quarter(date):
date = DT.datetime(date.year, date.month, date.day)
rr = rrule.rrule(
rrule.DAILY,
bymonth=(3,6,9,12), # the month must be one of these
bymonthday=-1, # the day has to be the last of the month
dtstart = date-DT.timedelta(days=100))
result = rr.before(date, inc=False) # inc=False ensures result < date
return result.date()
print(previous_quarter(DT.date(2013, 5, 31)))
# 2013-03-31
print(previous_quarter(DT.date(2013, 2, 1)))
# 2012-12-31
print(previous_quarter(DT.date(2013, 3, 31)))
# 2012-12-31
print(previous_quarter(DT.date(2013, 11, 1)))
# 2013-09-30
Exploit the data pattern involved and turn the problem into a table-lookup - your classic space-time tradeff:
from datetime import date
PQTBL = (((12,31,-1),)*3 + ((3,31,0),)*3 + ((6,30,0),)*3 + ((9,30,0),)*3)
def previous_quarter(ref):
entry = PQTBL[ref.month-1]
return date(ref.year+entry[2], entry[0], entry[1])
Find the first day and month of the quarter, then use relativedelta to subtract a day.
from dateutil.relativedelta import relativedelta
def previous_quarter(ref):
first_month_of_quarter = ((ref.month - 1) // 3) * 3 + 1
return ref.replace(month=first_month_of_quarter, day=1) - relativedelta(days=1)
It's almost certain you would be happier using pandas (a python library), it has many functions for "business time" data.
http://pandas.pydata.org/pandas-docs/dev/timeseries.html
Reworked Justin Ethier's code for a "next quarter" version. Also added timezone via pytz and strftime formatting. #justin-ethier
import pytz
from datetime import datetime, timedelta
import datetime as dt
def nextQuarter():
ref = datetime.now(pytz.timezone('America/New_York'))
if ref.month < 4:
next = dt.datetime(ref.year, 3, 31, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
elif ref.month < 7:
next = dt.datetime(ref.year, 6, 30, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
elif ref.month < 10:
next = dt.datetime(ref.year, 9, 30, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
else:
next = dt.datetime(ref.year + 1, 12, 31, 23, 59, 59).strftime('%m-%d-%Y %H:%M:%S')
return next
next = nextQuarter()
import datetime
def previous_quarter(ref):
quarter = (ref.month - 1) // 3
prev_quarter = (quarter - 1) % 4
return datetime.datetime(ref.year if quarter>0 else ref.year-1, prev_quarter*3+1, 1)
Solution using only python's datetime library -
import datetime
def get_quarter_end(dt):
'''
given a datetime object, find the end of the quarter
'''
quarter_of_month = int((dt.month-1)/3 + 1)
#======================================================
# find the first day of the next quarter
#======================================================
# if in last quarter then go to the next year
year = dt.year + 1 if quarter_of_month==4 else dt.year
# if in last quarter then month is january (or 1)
month = 1 if quarter_of_month==4 else (quarter_of_month*3) + 1
first_of_next_quarter = datetime.datetime(year = year,
month = month,
day = 1
)
# last day of quarter for dt will be minus 1 day of first of next quarter
quarter_end_dt = first_of_next_quarter - datetime.timedelta(days=1)
return quarter_end_dt
if __name__=='__main__':
dt = datetime.datetime.strptime('2016-07-15', '%Y-%m-%d')
target_dt = get_quarter_end(dt)
and if you want to retreive the last fours quarter you can do this
if ref.month < 4:
list1 = [datetime.date(ref.year - 1, 12, 31),
datetime.date(ref.year - 1, 9, 30),
datetime.date(ref.year - 1, 6, 30),
datetime.date(ref.year - 1, 3, 31)]
list1 = [i.strftime('%Y%m%d') for i in list1]
return list1
elif ref.month < 7:
return [datetime.date(ref.year, 3, 31),
datetime.date(ref.year - 1, 12, 31),
datetime.date(ref.year - 1, 9, 30),
datetime.date(ref.year - 1, 6, 30)]
elif ref.month < 10:
return [datetime.date(ref.year, 6, 30),
datetime.date(ref.year, 3, 31),
datetime.date(ref.year - 1, 12, 31),
datetime.date(ref.year - 1, 9, 30)]
return [datetime.date(ref.year, 9, 30),
datetime.date(ref.year, 6, 30),
datetime.date(ref.year, 3, 30),
datetime.date(ref.year - 1, 12, 31)]