I am new in programming. I came across this requirement. I have an array,
data= ['2016-1-01', '2016-1-08', '2016-1-15', '2016-1-22', '2016-1-29', '2016-02-05', '2016-02-12', '2016-02-19', '2016-02-26']
I have query result as following:
date a b c
2016-01-19 3 1 5
2016-01-20 10 4 5
2016-01-30 1 4 6
I am trying to generate the weekly report data.
In this example date '2016-01-19' and '2016-01-20' from above query lies between the '2016-01-15' and '2016-01-22' of data array so a, b & c is to be added.
The final output should like this:
2016-1-01 0 0 0
2016-1-08 0 0 0
2016-1-15 13 5 10
2016-1-22 0 0 0
2016-1-29 1 4 6
2016-2-05 0 0 0
2016-2-12 0 0 0
2016-2-19 0 0 0
2016-2-26 0 0 0
Assuming data is always sorted and has no repeated elements (you can do data = sorted(set(data)) if that is not the case), you can do something like this:
import datetime
data = ['2016-1-01', '2016-1-08', '2016-1-15', '2016-1-22', '2016-1-29', '2016-02-05', '2016-02-12', '2016-02-19', '2016-02-26']
query = [(datetime.date(2016, 1, 19), 3, 1, 5), (datetime.date(2016, 1, 20), 10, 4, 5), (datetime.date(2016, 1, 30), 1, 4, 6)]
# Convert data to datetime objects
data = [datetime.datetime.strptime(d, '%Y-%m-%d').date() for d in data]
output = []
query_it = iter(query)
next_date = data[0]
next_nums = (0, 0, 0)
# Iterate through date ranges
for d_start, d_end in zip(data, data[1:] + [datetime.date.max]):
# If the next interesting date is in range
if next_date < d_end:
nums = next_nums
next_nums = (0, 0, 0)
for q in query_it:
q_date, q_nums = q[0], q[1:]
if q_date < d_start:
# Ignore dates before the first date in data
continue
elif q_date < d_end:
# Add query numbers to count if in range
nums = tuple(n1 + n2 for n1, n2 in zip(nums, q_nums))
else:
# When out of range save numbers for next
next_date = q_date
next_nums = q_nums
break
else:
# Default to zero when no query dates in range
nums = (0, 0, 0)
# Add result to output
output.append((d_start,) + nums)
for out in output:
print(out)
Output:
(datetime.date(2016, 1, 1), 0, 0, 0)
(datetime.date(2016, 1, 8), 0, 0, 0)
(datetime.date(2016, 1, 15), 13, 5, 10)
(datetime.date(2016, 1, 22), 0, 0, 0)
(datetime.date(2016, 1, 29), 1, 4, 6)
(datetime.date(2016, 2, 5), 0, 0, 0)
(datetime.date(2016, 2, 12), 0, 0, 0)
(datetime.date(2016, 2, 19), 0, 0, 0)
(datetime.date(2016, 2, 26), 0, 0, 0)
This assumes that data is in order, otherwise use sorted(data).
import datetime
data = [
'2016-1-01', '2016-1-08', '2016-1-15',
'2016-1-22', '2016-1-29', '2016-02-05',
'2016-02-12', '2016-02-19', '2016-02-26'
]
query_result = [
(datetime.date(2016, 1, 19), 3, 1, 5),
(datetime.date(2016, 1, 20), 10, 4, 5),
(datetime.date(2016, 1, 30), 1, 4, 6)
]
# Convert string dates to datetime.date
date_data = [ datetime.datetime.strptime(date, '%Y-%m-%d').date()
for date in data ]
res = []
# zip the dates together in pairs
for start, end in zip(date_data, date_data[1:]):
tally_a = tally_b = tally_c = 0
for date, a, b, c in query_result:
# if date is in between add values
if start <= date <= end:
tally_a += a
tally_b += b
tally_c += c
res.append( (start, tally_a, tally_b, tally_c) )
# Output
for d, a, b, c in res:
print(d, a, b, c, sep = '\t')
2016-01-01 0 0 0
2016-01-08 0 0 0
2016-01-15 13 5 10
2016-01-22 0 0 0
2016-01-29 1 4 6
2016-02-05 0 0 0
2016-02-12 0 0 0
2016-02-19 0 0 0
I am trying to generate time interval array. for example:
time_array = ["2016-09-02T17:30:00Z", "2016-09-02T17:45:00Z",
"2016-09-02T18:00:00Z", "2016-09-02T18:15:00Z",
"2016-09-02T18:30:00Z", "2016-09-02T18:45:00Z"]
It should create the element like above in zulu time till 9 pm everyday.
Should generate the elements for next and day after next as well
Start time from 7:00 am - Ed time 9:00 pm,
if current_time is > start_time then generate 15 min time interval array till 9 pm. and then generate for next day and day + 2.
And Interval should be 7:00, 7:15 like that.. not in 7:12, 8:32
Here's a generic datetime_range for you to use.
Code
from datetime import datetime, timedelta
def datetime_range(start, end, delta):
current = start
while current < end:
yield current
current += delta
dts = [dt.strftime('%Y-%m-%d T%H:%M Z') for dt in
datetime_range(datetime(2016, 9, 1, 7), datetime(2016, 9, 1, 9+12),
timedelta(minutes=15))]
print(dts)
Output
['2016-09-01 T07:00 Z', '2016-09-01 T07:15 Z', '2016-09-01 T07:30 Z', '2016-09-01 T07:45 Z', '2016-09-01 T08:00 Z', '2016-09-01 T08:15 Z', '2016-09-01 T08:30 Z', '2016-09-01 T08:45 Z', '2016-09-01 T09:00 Z', '2016-09-01 T09:15 Z', '2016-09-01 T09:30 Z', '2016-09-01 T09:45 Z' ... ]
Here is a Pandas solution:
import pandas as pd
l = (pd.DataFrame(columns=['NULL'],
index=pd.date_range('2016-09-02T17:30:00Z', '2016-09-04T21:00:00Z',
freq='15T'))
.between_time('07:00','21:00')
.index.strftime('%Y-%m-%dT%H:%M:%SZ')
.tolist()
)
Output:
In [165]: l
Out[165]:
['2016-09-02T17:30:00Z',
'2016-09-02T17:45:00Z',
'2016-09-02T18:00:00Z',
'2016-09-02T18:15:00Z',
'2016-09-02T18:30:00Z',
'2016-09-02T18:45:00Z',
'2016-09-02T19:00:00Z',
'2016-09-02T19:15:00Z',
'2016-09-02T19:30:00Z',
'2016-09-02T19:45:00Z',
'2016-09-02T20:00:00Z',
'2016-09-02T20:15:00Z',
'2016-09-02T20:30:00Z',
'2016-09-02T20:45:00Z',
'2016-09-02T21:00:00Z',
'2016-09-03T07:00:00Z',
'2016-09-03T07:15:00Z',
'2016-09-03T07:30:00Z',
'2016-09-03T07:45:00Z',
'2016-09-03T08:00:00Z',
'2016-09-03T08:15:00Z',
'2016-09-03T08:30:00Z',
'2016-09-03T08:45:00Z',
'2016-09-03T09:00:00Z',
'2016-09-03T09:15:00Z',
'2016-09-03T09:30:00Z',
'2016-09-03T09:45:00Z',
'2016-09-03T10:00:00Z',
'2016-09-03T10:15:00Z',
'2016-09-03T10:30:00Z',
'2016-09-03T10:45:00Z',
'2016-09-03T11:00:00Z',
'2016-09-03T11:15:00Z',
'2016-09-03T11:30:00Z',
'2016-09-03T11:45:00Z',
'2016-09-03T12:00:00Z',
'2016-09-03T12:15:00Z',
'2016-09-03T12:30:00Z',
'2016-09-03T12:45:00Z',
'2016-09-03T13:00:00Z',
'2016-09-03T13:15:00Z',
'2016-09-03T13:30:00Z',
'2016-09-03T13:45:00Z',
'2016-09-03T14:00:00Z',
'2016-09-03T14:15:00Z',
'2016-09-03T14:30:00Z',
'2016-09-03T14:45:00Z',
'2016-09-03T15:00:00Z',
'2016-09-03T15:15:00Z',
'2016-09-03T15:30:00Z',
'2016-09-03T15:45:00Z',
'2016-09-03T16:00:00Z',
'2016-09-03T16:15:00Z',
'2016-09-03T16:30:00Z',
'2016-09-03T16:45:00Z',
'2016-09-03T17:00:00Z',
'2016-09-03T17:15:00Z',
'2016-09-03T17:30:00Z',
'2016-09-03T17:45:00Z',
'2016-09-03T18:00:00Z',
'2016-09-03T18:15:00Z',
'2016-09-03T18:30:00Z',
'2016-09-03T18:45:00Z',
'2016-09-03T19:00:00Z',
'2016-09-03T19:15:00Z',
'2016-09-03T19:30:00Z',
'2016-09-03T19:45:00Z',
'2016-09-03T20:00:00Z',
'2016-09-03T20:15:00Z',
'2016-09-03T20:30:00Z',
'2016-09-03T20:45:00Z',
'2016-09-03T21:00:00Z',
'2016-09-04T07:00:00Z',
'2016-09-04T07:15:00Z',
'2016-09-04T07:30:00Z',
'2016-09-04T07:45:00Z',
'2016-09-04T08:00:00Z',
'2016-09-04T08:15:00Z',
'2016-09-04T08:30:00Z',
'2016-09-04T08:45:00Z',
'2016-09-04T09:00:00Z',
'2016-09-04T09:15:00Z',
'2016-09-04T09:30:00Z',
'2016-09-04T09:45:00Z',
'2016-09-04T10:00:00Z',
'2016-09-04T10:15:00Z',
'2016-09-04T10:30:00Z',
'2016-09-04T10:45:00Z',
'2016-09-04T11:00:00Z',
'2016-09-04T11:15:00Z',
'2016-09-04T11:30:00Z',
'2016-09-04T11:45:00Z',
'2016-09-04T12:00:00Z',
'2016-09-04T12:15:00Z',
'2016-09-04T12:30:00Z',
'2016-09-04T12:45:00Z',
'2016-09-04T13:00:00Z',
'2016-09-04T13:15:00Z',
'2016-09-04T13:30:00Z',
'2016-09-04T13:45:00Z',
'2016-09-04T14:00:00Z',
'2016-09-04T14:15:00Z',
'2016-09-04T14:30:00Z',
'2016-09-04T14:45:00Z',
'2016-09-04T15:00:00Z',
'2016-09-04T15:15:00Z',
'2016-09-04T15:30:00Z',
'2016-09-04T15:45:00Z',
'2016-09-04T16:00:00Z',
'2016-09-04T16:15:00Z',
'2016-09-04T16:30:00Z',
'2016-09-04T16:45:00Z',
'2016-09-04T17:00:00Z',
'2016-09-04T17:15:00Z',
'2016-09-04T17:30:00Z',
'2016-09-04T17:45:00Z',
'2016-09-04T18:00:00Z',
'2016-09-04T18:15:00Z',
'2016-09-04T18:30:00Z',
'2016-09-04T18:45:00Z',
'2016-09-04T19:00:00Z',
'2016-09-04T19:15:00Z',
'2016-09-04T19:30:00Z',
'2016-09-04T19:45:00Z',
'2016-09-04T20:00:00Z',
'2016-09-04T20:15:00Z',
'2016-09-04T20:30:00Z',
'2016-09-04T20:45:00Z',
'2016-09-04T21:00:00Z']
Looking at the data file, you should use the built in python date-time objects. followed by strftime to format your dates.
Broadly you can modify the code below to however many date-times you would like
First create a starting date.
Today= datetime.datetime.today()
Replace 100 with whatever number of time intervals you want.
date_list = [Today + datetime.timedelta(minutes=15*x) for x in range(0, 100)]
Finally, format the list in the way that you would like, using code like that below.
datetext=[x.strftime('%Y-%m-%d T%H:%M Z') for x in date_list]
Here is an example using an arbitrary date time
from datetime import datetime
start = datetime(1900,1,1,0,0,0)
end = datetime(1900,1,2,0,0,0)
Now you need to get the timedelta (the difference between two dates or times.) between the start and end
seconds = (end - start).total_seconds()
Define the 15 minutes interval
from datetime import timedelta
step = timedelta(minutes=15)
Iterate over the range of seconds, with step of time delta of 15 minutes (900 seconds) and sum it to start.
array = []
for i in range(0, int(seconds), int(step.total_seconds())):
array.append(start + timedelta(seconds=i))
print array
[datetime.datetime(1900, 1, 1, 0, 0),
datetime.datetime(1900, 1, 1, 0, 15),
datetime.datetime(1900, 1, 1, 0, 30),
datetime.datetime(1900, 1, 1, 0, 45),
datetime.datetime(1900, 1, 1, 1, 0),
...
At the end you can format the datetime objects to str representation.
array = [i.strftime('%Y-%m-%d %H:%M%:%S') for i in array]
print array
['1900-01-01 00:00:00',
'1900-01-01 00:15:00',
'1900-01-01 00:30:00',
'1900-01-01 00:45:00',
'1900-01-01 01:00:00',
...
You can format datetime object at first iteration. But it may hurt your eyes
array.append((start + timedelta(seconds=i)).strftime('%Y-%m-%d %H:%M%:%S'))
I'll provide a solution that does not handle timezones, since the problem is generating dates and times and you can set the timezone afterwards however you want.
You have a starting date and starting and ending time (for each day), plus an interval (in minutes) for these datetimes. The idea is to create a timedelta object that represent the time interval and repeatedly update the datetime until we reach the ending time, then we advance by one day and reset the time to the initial one and repeat.
A simple implementation could be:
def make_dates(start_date, number_of_days, start_time, end_time, interval, timezone):
if isinstance(start_date, datetime.datetime):
start_date = start_date.date()
start_date = datetime.datetime.combine(start_date, start_time)
cur_date = start_date
num_days_passed = 0
step = datetime.timedelta(seconds=interval*60)
while True:
new_date = cur_date + step
if new_date.time() > end_time:
num_days_passed += 1
if num_days_passed > number_of_days:
break
new_date = start_date + datetime.timedelta(days=num_days_passed)
ret_date, cur_date = cur_date, new_date
yield ret_date
In [31]: generator = make_dates(datetime.datetime.now(), 3, datetime.time(hour=17), datetime.time(hour=19), 15, None)
In [32]: next(generator)
Out[32]: datetime.datetime(2016, 9, 2, 17, 0)
In [33]: next(generator)
Out[33]: datetime.datetime(2016, 9, 2, 17, 15)
In [34]: list(generator)
Out[34]:
[datetime.datetime(2016, 9, 2, 17, 30),
datetime.datetime(2016, 9, 2, 17, 45),
datetime.datetime(2016, 9, 2, 18, 0),
datetime.datetime(2016, 9, 2, 18, 15),
datetime.datetime(2016, 9, 2, 18, 30),
datetime.datetime(2016, 9, 2, 18, 45),
datetime.datetime(2016, 9, 2, 19, 0),
datetime.datetime(2016, 9, 3, 17, 0),
datetime.datetime(2016, 9, 3, 17, 15),
datetime.datetime(2016, 9, 3, 17, 30),
datetime.datetime(2016, 9, 3, 17, 45),
datetime.datetime(2016, 9, 3, 18, 0),
datetime.datetime(2016, 9, 3, 18, 15),
datetime.datetime(2016, 9, 3, 18, 30),
datetime.datetime(2016, 9, 3, 18, 45),
datetime.datetime(2016, 9, 3, 19, 0),
datetime.datetime(2016, 9, 4, 17, 0),
datetime.datetime(2016, 9, 4, 17, 15),
datetime.datetime(2016, 9, 4, 17, 30),
datetime.datetime(2016, 9, 4, 17, 45),
datetime.datetime(2016, 9, 4, 18, 0),
datetime.datetime(2016, 9, 4, 18, 15),
datetime.datetime(2016, 9, 4, 18, 30),
datetime.datetime(2016, 9, 4, 18, 45),
datetime.datetime(2016, 9, 4, 19, 0),
datetime.datetime(2016, 9, 5, 17, 0),
datetime.datetime(2016, 9, 5, 17, 15),
datetime.datetime(2016, 9, 5, 17, 30),
datetime.datetime(2016, 9, 5, 17, 45),
datetime.datetime(2016, 9, 5, 18, 0),
datetime.datetime(2016, 9, 5, 18, 15),
datetime.datetime(2016, 9, 5, 18, 30),
datetime.datetime(2016, 9, 5, 18, 45)]
Once you have the datetimes you can use the strftime method to convert them to strings.
This is the final script I have written based on the answers posted on my question:
from datetime import datetime
from datetime import timedelta
import calendar
current_utc = datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S")
current_year = int(current_utc.split("-")[0])
current_month = int(current_utc.split("-")[1])
current_date = int(current_utc.split("-")[2])
current_hour = int(current_utc.split("-")[3])
current_min = int(current_utc.split("-")[4])
current_sec = int(current_utc.split("-")[5])
#### To make minutes round to quarter ####
min_range_1 = range(1,16)
min_range_2 = range(16,31)
min_range_3 = range(31,46)
min_range_4 = range(46,60)
if current_min in min_range_1:
current_min = 15
elif current_min in min_range_2:
current_min = 30
elif current_min in min_range_3:
current_min = 45
elif current_min in min_range_4:
current_hour = current_hour + 1
current_min = 0
else:
print("Please check current minute.")
current_sec = 00
date_range_31 = range(1,32)
date_range_30 = range(1,31)
month_days_31 = [1,3,5,7,8,10,12]
month_days_30 = [4,6,9,11]
if current_month in month_days_31:
if current_date == 31:
next_day_month = current_month + 1
next_day_date = 1
else:
next_day_month = current_month
next_day_date = current_date
elif current_month == 2:
if calendar.isleap(current_year):
if current_date == 29:
next_day_month = current_month + 1
next_day_date = 1
else:
next_day_month = current_month
next_day_date = current_date
else:
if current_date == 28:
next_day_month = current_month + 1
next_day_date = 1
else:
next_day_month = current_month
next_day_date = current_date
elif current_month in month_days_30:
if current_date == 30:
next_day_month = current_month + 1
next_day_date = 1
else:
next_day_month = current_month
next_day_date = current_date
else:
print("Please check the current month and date to procedd further.")
if current_hour < 11:
current_hour = 11
current_min = 15
next_day_date = current_date + 1
current_start = datetime(current_year,current_month,current_date,current_hour,current_min,current_sec)
current_end = datetime(current_year,current_month,current_date,21,15,0)
next_day_start = datetime(current_year,next_day_month,next_day_date,11,15,0)
next_day_end = datetime(current_year,next_day_month,next_day_date,21,15,0)
current_seconds = (current_end - current_start).total_seconds()
next_day_seconds = (next_day_end - next_day_start).total_seconds()
step = timedelta(minutes=15)
current_day_array = []
next_day_array = []
for i in range(0, int(current_seconds), int(step.total_seconds())):
current_day_array.append(current_start + timedelta(seconds=i))
for i in range(0, int(next_day_seconds), int(step.total_seconds())):
current_day_array.append(next_day_start + timedelta(seconds=i))
current_day_array = [i.strftime('%Y-%m-%dT%H:%M%:%SZ') for i in current_day_array]
print current_day_array
Which produces the following output:
['2016-09-03T11:15:00Z', '2016-09-03T11:30:00Z', '2016-09-03T11:45:00Z', '2016-09-03T12:00:00Z', '2016-09-03T12:15:00Z', '2016-09-03T12:30:00Z', '2016-09-03T12:45:00Z', '2016-09-03T13:00:00Z', '2016-09-03T13:15:00Z', '2016-09-03T13:30:00Z', '2016-09-03T13:45:00Z', '2016-09-03T14:00:00Z', '2016-09-03T14:15:00Z', '2016-09-03T14:30:00Z', '2016-09-03T14:45:00Z', '2016-09-03T15:00:00Z', '2016-09-03T15:15:00Z', '2016-09-03T15:30:00Z', '2016-09-03T15:45:00Z', '2016-09-03T16:00:00Z', '2016-09-03T16:15:00Z', '2016-09-03T16:30:00Z', '2016-09-03T16:45:00Z', '2016-09-03T17:00:00Z', '2016-09-03T17:15:00Z', '2016-09-03T17:30:00Z', '2016-09-03T17:45:00Z', '2016-09-03T18:00:00Z', '2016-09-03T18:15:00Z', '2016-09-03T18:30:00Z', '2016-09-03T18:45:00Z', '2016-09-03T19:00:00Z', '2016-09-03T19:15:00Z', '2016-09-03T19:30:00Z', '2016-09-03T19:45:00Z', '2016-09-03T20:00:00Z', '2016-09-03T20:15:00Z', '2016-09-03T20:30:00Z', '2016-09-03T20:45:00Z', '2016-09-03T21:00:00Z', '2016-09-04T11:15:00Z', '2016-09-04T11:30:00Z', '2016-09-04T11:45:00Z', '2016-09-04T12:00:00Z', '2016-09-04T12:15:00Z', '2016-09-04T12:30:00Z', '2016-09-04T12:45:00Z', '2016-09-04T13:00:00Z', '2016-09-04T13:15:00Z', '2016-09-04T13:30:00Z', '2016-09-04T13:45:00Z', '2016-09-04T14:00:00Z', '2016-09-04T14:15:00Z', '2016-09-04T14:30:00Z', '2016-09-04T14:45:00Z', '2016-09-04T15:00:00Z', '2016-09-04T15:15:00Z', '2016-09-04T15:30:00Z', '2016-09-04T15:45:00Z', '2016-09-04T16:00:00Z', '2016-09-04T16:15:00Z', '2016-09-04T16:30:00Z', '2016-09-04T16:45:00Z', '2016-09-04T17:00:00Z', '2016-09-04T17:15:00Z', '2016-09-04T17:30:00Z', '2016-09-04T17:45:00Z', '2016-09-04T18:00:00Z', '2016-09-04T18:15:00Z', '2016-09-04T18:30:00Z', '2016-09-04T18:45:00Z', '2016-09-04T19:00:00Z', '2016-09-04T19:15:00Z', '2016-09-04T19:30:00Z', '2016-09-04T19:45:00Z', '2016-09-04T20:00:00Z', '2016-09-04T20:15:00Z', '2016-09-04T20:30:00Z', '2016-09-04T20:45:00Z', '2016-09-04T21:00:00Z']
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)]