Python last 60 end-of-months [duplicate] - python

This question already has answers here:
How to get the last day of the month?
(44 answers)
Closed 8 years ago.
This is my first post here so please let me know if I'm doing this wrong...
I'm looking to take the last day of each month for the last 60 months, from a reference date.
For example, if the reference date is today (Aug 21 2014), then the last end of month is July 31st, 2014, and the one before that is June 30th, 2014...
Does anyone know how to do this in python?
Thanks!

Here's an easier/cleaner way that makes use of the datetime module:
>>> import datetime
>>> def prevMonthEnd(startDate):
... ''' given a datetime object, return another datetime object that
... is set to the last day of the prevoius month '''
... firstOfMonth = startDate.replace(day=1)
... return firstOfMonth - datetime.timedelta(days=1)
...
>>> theDate = datetime.date.today()
>>> for i in range(60):
... theDate = prevMonthEnd(theDate)
... print theDate
...
2014-07-31
2014-06-30
2014-05-31
2014-04-30
2014-03-31
2014-02-28
2014-01-31
2013-12-31
(etc.)

Figured it out:
import calendar
m = int(raw_input("m: "))
y = int(raw_input("y: "))
meArr = []
monthsleft = 60
for i in range(1,int(m)):
meArr = meArr + [str(calendar.monthrange(y,i)[1]) + '.' + str(i) + '.' + str(y)]
monthsleft = monthsleft - len(meArr)
while monthsleft > 0:
if monthsleft >= 12:
y = y - 1
for i in range(12,0,-1):
meArr = [str(calendar.monthrange(y,i)[1]) + '.' + str(i) + '.' + str(y)] + meArr
else:
y = y - 1
for i in range(12,m-1,-1):
meArr = [str(calendar.monthrange(y,i)[1]) + '.' + str(i) + '.' + str(y)] + meArr
monthsleft = monthsleft - 12
## print(len(meArr))

Related

How to convert A "hours and minutes and seconds" string to HH:MM:SS format?

In python, I am trying to make an alarm system where it converts "x Hours y Minutes and z Seconds" to the x:y:z format
For example:
5 hours 20 minutes 6 seconds
05:20:06
1 hour 25 seconds
01:00:25
This is my code, but it seems scuffed:
time_string = '1 hour and 25 seconds'
correction = time_string.replace('and ', '')
duration = correction.replace(' hour', ':').replace(' minute', ':').replace(' second', ':').replace(' ','').replace('s', '')
if 'minute' not in correction and 'second' not in correction:
duration = duration + '00:00'
elif 'minute' not in correction and 'second' in correction:
duration = duration.replace(':',':00:')
elif 'second' not in correction:
duration = duration + '00'
secs = sum(int(x) * 60 ** i for i, x in enumerate(reversed(duration.split(':'))))
How do I improve it?
This returns total number of seconds, which seems to be what you wanted:
def parsex(s):
hh = mm = ss = 0
for word in s.split():
word = word.lower()
if word.isdigit():
save = word
elif word.startswith('hour'):
hh = int(save)
elif word.startswith('minute'):
mm = int(save)
elif word.startswith('second'):
ss = int(save)
return (hh*60+mm)*60+ss
print(parsex('1 hour and 30 seconds'))
print(parsex('2 hours 15 minutes 45 seconds'))
You can use datetime library to convert this type of string to proper formatted string.
from datetime import datetime
def format_time(string):
format_string = ''
if 'hour' in string:
if 'hours' in string:
format_string += '%H hours '
else:
format_string += '%H hour '
if 'minute' in string:
if 'minutes' in string:
format_string += '%M minutes '
else:
format_string += '%M minute '
if 'second' in string:
if 'seconds' in string:
format_string += '%S seconds'
else:
format_string += '%S second'
value = datetime.strptime(string, format_string)
return value.strftime('%H:%M:%S')
string = '5 hours 20 minutes 6 seconds'
print(format_time(string))
string = '1 hour 25 seconds'
print(format_time(string))
string = '1 minute 25 seconds'
print(format_time(string))
Output
05:20:06
01:00:25
00:01:25
from collections import defaultdict
dataexp = [
("5 hours 20 minutes 6 seconds","05:20:06"),
("1 hour 25 seconds","01:00:25")
]
def convert(input_):
words = input_.replace('and','').split()
di = defaultdict(lambda:0)
while words:
num = int(words.pop(0))
unit = words.pop(0)[0]
di[unit] = num
return f"{di['h']:02}:{di['m']:02}:{di['s']:02}"
for inp, exp in dataexp:
got = convert(inp)
msg = "\nfor %-100.100s \nexp :%s:\ngot :%s:\n" % (inp, exp, got)
if exp == got:
print("✅! %s" % msg)
else:
print("❌! %s" % msg)
which outputs:
✅!
for 5 hours 20 minutes 6 seconds
exp :05:20:06:
got :05:20:06:
✅!
for 1 hour 25 seconds
exp :01:00:25:
got :01:00:25:

How do I find what the date will be next Sunday 12 am from now and then add 10 hours to it

I have this code
today = datetime.now().date()
# prints: 2022/1/14
rd = REL.relativedelta(days=1, weekday=REL.SU)
nextSunday = today + rd
#prints : 2022/1/16
How do i add 10 hours to the date so i can get a variable nextSunday_10am that i can substract to the current time
difference = nextSunday_10am - today
and schedule what I need to do
You can do the same thing as suggested by #Dani3le_ more directly with the following:
def getSundayTime(tme: datetime.date) -> datetime:
nxt_sndy = tme + timedelta(days= 6 - tme.weekday())
return datetime.combine(nxt_sndy, datetime.strptime('10:00', '%H:%M').time())
This will compute calculate the next Sunday and set time to 10:00
You can add hours to a DateTime by using datetime.timedelta().
nextSunday += datetime.timedelta(hours=10)
For example:
import datetime
today = datetime.datetime.today()
print("Today is "+str(today))
while today.weekday()+1 != 6: #0 = "Monday", 1 = "Tuesday"...
today += datetime.timedelta(1)
nextSunday = today + datetime.timedelta(hours=10)
print("Next sunday +10hrs will be "+str(nextSunday))

Getting dates in python between a past datestamp and the present

Language Python
I am wondering if anyone can help me print out some dates.
i cam trying to create a loop in which i pass in a date say 01/1/2017 and the loop will then output the first and last day in every month between then and the present day.
Example
01/01/2017
31/01/2017
01/02/2017
28/02/2017
etc
Any help will be appreciated
Hope this will help,
Code:
from datetime import date
from dateutil.relativedelta import relativedelta
from calendar import monthrange
d1 = date(2018, 2, 26)
d2 = date.today()
def print_month_day_range(date):
first_day = date.replace(day = 1)
last_day = date.replace(day = monthrange(date.year, date.month)[1])
print (first_day.strftime("%d/%m/%Y"))
print (last_day.strftime("%d/%m/%Y"))
print_month_day_range(d1)
while (d1 < d2):
d1 = d1 + relativedelta(months=1)
print_month_day_range(d1)
Output:
01/02/2018
28/02/2018
01/03/2018
31/03/2018
...
01/07/2018
31/07/2018
you can use calendar module. Below is the code:
import datetime
from calendar import monthrange
strt_date = '01/1/2017'
iter_year = datetime.datetime.strptime(strt_date, '%m/%d/%Y').year
iter_month = datetime.datetime.strptime(strt_date, '%m/%d/%Y').month
cur_year = datetime.datetime.today().year
cur_month = datetime.datetime.today().month
while cur_year > iter_year or (cur_year == iter_year and iter_month <= cur_month):
number_of_days_in_month = monthrange(iter_year, iter_month)[1]
print '/'.join([str(iter_month) , '01', str(iter_year)])
print '/'.join([str(iter_month), str(number_of_days_in_month), str(iter_year)])
if iter_month == 12:
iter_year += 1
iter_month = 1
else:
iter_month += 1
this could work, as long as the first date you give is always the first of the month
from datetime import datetime
from datetime import timedelta
date_string = '01/01/2017'
date = datetime.strptime(date_string, '%d/%m/%Y').date()
today = datetime.now().date()
months = range(1,13)
years = range(date.year, today.year + 1)
for y in years:
for m in months:
new_date = date.replace(month=m, year=y)
last_day = new_date - timedelta(days=1)
if (date < new_date) & (new_date <= today):
print last_day.strftime('%d/%m/%Y')
print new_date.strftime('%d/%m/%Y')
elif (date <= new_date) & (new_date <= today):
print new_date.strftime('%d/%m/%Y')
This code would print the first and last days of all months in a year.
Maybe add some logic to iterate through the years
import datetime
def first_day_of_month(any_day):
first_month = any_day.replace(day=1)
return first_month
def last_day_of_month(any_day):
next_month = any_day.replace(day=28) + datetime.timedelta(days=4)
return next_month - datetime.timedelta(days=next_month.day)
for month in range(1, 13):
print first_day_of_month(datetime.date(2017, month, 1))
print last_day_of_month(datetime.date(2017, month, 1))

Count summer days between two dates

I want to count summer days between two dates. Summer is May first to August last.
This will count all days:
import datetime
startdate=datetime.datetime(2015,1,1)
enddate=datetime.datetime(2016,6,1)
delta=enddate-startdate
print delta.days
>>517
But how can only count the passed summer days?
You could define a generator to iterate over every date between startdate and enddate, define a function to check if a date represents a summer day and use sum to count the summer days:
import datetime
startdate = datetime.datetime(2015,1,1)
enddate = datetime.datetime(2016,6,1)
all_dates = (startdate + datetime.timedelta(days=x) for x in range(0, (enddate-startdate).days))
def is_summer_day(date):
return 5 <= date.month <= 8
print(sum(1 for date in all_dates if is_summer_day(date)))
# 154
Thanks to the generator, you don't need to create a huge list in memory with every day between startdate and enddate.
This iteration still considers every single day, even if it's not needed. For very large gaps, you could use the fact that every complete year has 123 summer days according to your definition.
You can create a few functions to count how many summer days you have between two days:
from datetime import date
def get_summer_start(year):
return date(year, 5, 1)
def get_summer_end(year):
return date(year, 8, 31)
def get_start_date(date, year):
return max(date, get_summer_start(year))
def get_end_date(date, year):
return min(date, get_summer_end(year))
def count_summer_days(date1, date2):
date1_year = date1.year
date2_year = date2.year
if date1_year == date2_year:
s = get_start_date(date1, date1_year)
e = get_end_date(date2, date1_year)
return (e - s).days
else:
s1 = max(date1, get_summer_start(date1_year))
e1 = get_summer_end(date1_year)
first_year = max(0,(e1 -s1).days)
s1 = get_summer_start(date2_year)
e1 = min(date2, get_summer_end(date2_year))
last_year = max(0,(e2 -s2).days)
other_years = date2_year - date1_year - 1
summer_days_per_year = (get_summer_end(date1_year) - get_summer_start(date1_year)).days
return first_year + last_year + (other_years * summer_days_per_year)
date1 = date(2015,1,1)
date2 = date(2016,6,1)
print count_summer_days(date1, date2)
Here is a better solution for large periods:
first_summer_day = (5,1)
last_summer_day = (8,31)
from datetime import date
startdate = date(2015,1,1)
enddate = date(2016,6,1)
# make sure that startdate > endate
if startdate > enddate:
startdate, endate = endate, startdate
def iter_yearly_summer_days(startdate, enddate):
for year in range(startdate.year, enddate.year+1):
start_period = startdate if year == startdate.year else date(year, 1, 1)
end_period = enddate if year == enddate.year else date(year, 12, 31)
year_first_summer_day = date(year, *first_summer_day)
year_last_summer_day = date(year, *last_summer_day)
summer_days_that_year = (min(year_last_summer_day, end_period) - max(year_first_summer_day, start_period)).days
print('year {} had {} days of summer'.format(year, summer_days_that_year))
yield summer_days_that_year
print(sum(iter_yearly_summer_days(startdate, enddate)))

Calculating time difference from unix $date

I have pairs of timestamps from the unix date:
alvas#ubi:~$ date
Wed May 20 01:04:43 CEST 2015
How can I calculate the time difference between the pairs of timestamp?
Note: I don't have the full datetime stamp from $date but only the time in hr:min:sec left in my logfile.
For example, timediff(start, end):
timediff('11:12:10', '19:58:50')
timediff('15:17:09', '03:11:10')
[out]:
31600
42841
[out2]:
8 hrs 46 mins 40 secs (31600 secs)
11 hrs 54 mins 1 secs (42841 secs)
In the case that end < start, treat it as the next day.
I've tried the script below but is there an easier way to do that?
def timediff(start, end):
start_hr, start_min, start_sec = map(float, start.split(':'))
end_hr, end_min, end_sec = map(float, end.split(':'))
if end_hr < start_hr:
end_hr = end_hr + 24
if end_min < start_min:
end_min = end_min + 60
end_hr -= 1
if end_sec < start_sec:
end_sec = end_sec + 60
end_min -= 1
num_hrs = end_hr - start_hr
num_mins = end_min - start_min
num_secs = end_sec - start_sec
total_seconds = 60*60*num_hrs + 60*num_mins+num_secs
total_time = " ".join([str(num_hrs), 'hrs', str(num_mins), 'mins', str(num_secs), 'secs'])
return total_seconds, total_time
print timediff('11:12:10', '19:58:50')
print timediff('15:17:09', '03:11:10')
[out]:
(31600.0, '8.0 hrs 46.0 mins 40.0 secs')
(42841.0, '11.0 hrs 54.0 mins 1.0 secs')
When I tried dateutil.parser.parse:
>>> from dateutil.parser import parse as dtparse
>>> dtparse('19:58:50') - dtparse('11:12:10')
datetime.timedelta(0, 31600)
>>> dtparse('03:11:10') - dtparse('15:17:09')
datetime.timedelta(-1, 42841)
dateutil.parser(pip install python-dateutil) can parse just about anything ... and its timezone aware
from dateutil.parser import parse as dtparse
print dtparse("Wed May 20 01:04:43 CEST 2015") - dtparse("Wed May 20 00:02:43 CEST 2015")
>>> print dtparse("Fri May 22 01:04:43 CEST 2015") - dtparse("Wed May 20 00:02:43
CEST 2015")
2 days, 1:02:00
>>> print dtparse("15:22:36") - dtparse("12:00:45")
3:21:51 # 3 hours, 21 minutes, 51 seconds
here ... this will work if you dont know which timestamp is later ...
def tdiff(t1,t2):
if t1 > t2:t1,t2 = t2,t1
return t2-t1
print tdiff(dtparse('11:12:10'), dtparse('19:58:50'))
if you want to subtract a day in the event the order is wrong try this
def tdiff(t1,t2):
if t1 > t2:t1 - datetime.timedelta(days=1)
return t2-t1
Probably easier to use datetime:
import datetime
def timediff(t1, t2):
d1=datetime.datetime.strptime(t1, "%H:%M:%S")
d2=datetime.datetime.strptime(t2, "%H:%M:%S")
if d2<d1:
d1-=datetime.timedelta(days=1)
return ((d2-d1).total_seconds(), str(d2-d1))
>>> timediff('11:12:10', '19:58:50')
(31600.0, '8:46:40')
>>> timediff('15:17:09', '03:11:10')
(42841.0, '11:54:01')

Categories