How do I perform timedelta and date comparison in Ruby? - python

In Python, if I want to check for a specific date + 24 hours has passed, I will write:
from datetime import datetime, timedelta
some_date = datetime(2013, 1, 10, 11, 0)
day = timedelta(1)
# Checks if some_date + 1 day is before today's date
print some_date + day < datetime.now()
How can I construct a time difference of 1 day and checks if a specific date + 1 day is before today's date in Ruby?

require 'time'
xmas = DateTime.new(2013, 12, 25)
puts x = xmas + 1 # 2013-12-26T00:00:00+00:00
d = DateTime.now
puts x > d # true
puts x - d # 30167183979194791/86400000000000 (a Rational)
puts d >> 12 # 2014-01-10T21:15:20+01:00

Related

Changing month_id when looping over dates in python

I want to create a dictionary of dates where I have an id for each day, and a month id for each day in a specific month. Like:
id
month_id
date
1
1
2021-01-01
2
1
2021-01-02
3
1
2021-01-03
...
...
....
32
2
2021-02-01
33
2
2021-02-02
...
I have the following code so far:
def create_date_table():
d1 = date(2021, 1, 1)
d2 = date(2022, 12, 31)
delta = d2 - d1
dates = []
date_id = 1
month_id = 1
for i in range(delta.days + 1):
full_date = (d1 + timedelta(days=i)).strftime('%Y-%m-%d')
dates.append({'id': date_id,
'month_id': month_id,
'date': full_date})
date_id+=1
#increase the month_id here when month changes
print(dates)
I am not sure how to check when a month changes in the for loop. It is important that 2022 January's month_id should be 13, not 1 again. Any guidance would be greatly appreciated.
You need to keep track of the month and if it changes increase the month_id as below
def create_date_table():
d1 = date(2021, 1, 1)
d2 = date(2022, 12, 31)
delta = d2 - d1
dates = []
date_id = 1
month_id = 1
last_month = d1.month
for i in range(delta.days + 1):
new_date = (d1 + timedelta(days=i))
full_date = new_date.strftime('%Y-%m-%d')
dates.append({'id': date_id,
'month_id': month_id,
'date': full_date})
date_id+=1
#increase the month_id here when month changes
if last_month != new_date.month:
last_month = new_date.month
month_id+=1
print(dates)
Save the first value of the month you want to start with(last_month variable).
In the loop, take the month value of full_date then compare this with last_month. If it changes, increase month_id.
def create_date_table():
d1 = date(2021, 1, 1)
d2 = date(2022, 12, 31)
delta = d2 - d1
dates = []
date_id = 1
month_id = 1
last_month = int(d1.month) # assigns the first month value to last_month variable
for i in range(delta.days + 1):
full_date = (d1 + timedelta(days=i)).strftime('%Y-%m-%d')
month = int(full_date.split('-')[1]) # split full_date to ['year', 'month', 'day'] then take month value
if month-last_month != 0: # if month changes
month_id += 1 # increase month_id
last_month = month # reset last_month
dates.append({'id': date_id,
'month_id': month_id,
'date': full_date})
date_id+=1
print(dates)
Create a stateless Closure:
from datetime import date, timedelta
def create_date_table():
d1 = date(2021, 1, 1)
d2 = date(2022, 12, 31)
delta = d2 - d1
dates = []
date_id = 1
month_id = 1
month_counter = 1 # This resets at every time the month changes
def month_cal(month_): # Closure
nonlocal month_id
nonlocal month_counter
month_ = int(month_)
month_id += 1
month_counter = month_
for i in range(delta.days + 1):
full_date = (d1 + timedelta(days=i)).strftime('%Y-%m-%d')
current_month = full_date.split('-')[1] # Grab Month
if int(current_month) != month_counter:
month_cal(current_month)
dates.append({'id': date_id,
'month_id': month_id,
'date': full_date})
date_id+=1
print(dates)
create_date_table()

I want to find the month name of 2018 where there are 5 Sundays or more

My problem is to find the month name of 2018 where there are 5 Sundays or more... I cannot do it. Does anyone has an idea how to solve this ?
You can just count it:
from collections import Counter
from datetime import date, timedelta
SUNDAY = 6
c = Counter()
for i in range(365):
day = date(2018, 1, 1) + timedelta(days=i)
if day.weekday() == SUNDAY:
c[day.month] += 1
# prints {4, 7, 9, 12}
print({month for month in c if c[month] >= 5})

Pandas Week of Year from July 1

So I have pandas dataframe with a 'date' column. Our calendar is based off of July 1st being the first day. I know I can do df['date'].dt.week, but that gives me the week from Jan 1. Is there a way to take my df and make a new column 'week' where 'week' is 0 for the first days in July until Sunday and then 1... etc.? Basically the same way that dt.week works... just shifted to Jul 1. I know that resample allows me to shift this way, I just can't seem to figure out how to get it all correct as a column.
Thanks
Update: Currently doing this... not exactly working.
def get_academic_year(x):
if (x.month < 7):
year = x.year - 1
else:
year = x.year
return year
def get_week(x):
return ((x['date'].week -
pd.to_datetime(pd.datetime(x['academic_year'], 7, 1)).week) % 52)
df_x['academic_year'] = df_x['date'].apply(lambda x: get_academic_year(x))
df_x['week'] = df_x.apply(lambda x: get_week(x), axis=1)
My Dataset:
'{"date":{"0":1414368000000,"1":1414454400000,"2":1414540800000,"3":1414627200000,"4":1414713600000,"5":1414800000000,"6":1414886400000,"7":1425254400000,"8":1425340800000,"9":1425427200000,"10":1425513600000,"11":1425600000000,"12":1425686400000,"13":1425772800000,"14":1433116800000,"15":1433203200000,"16":1433289600000,"17":1433376000000,"18":1433462400000,"19":1433548800000,"20":1433635200000,"21":1444262400000,"22":1444348800000,"23":1444608000000,"24":1444694400000,"25":1444780800000,"26":1444867200000,"27":1444953600000,"28":1445040000000,"29":1445126400000,"30":1452643200000,"31":1452729600000,"32":1452816000000,"33":1452902400000,"34":1452988800000,"35":1460505600000,"36":1460937600000,"37":1461024000000,"38":1461110400000,"39":1461196800000,"40":1461283200000,"41":1461369600000,"42":1461456000000,"43":1465776000000,"44":1465862400000,"45":1465948800000,"46":1466035200000,"47":1466121600000,"48":1470873600000,"49":1470960000000,"50":1471219200000,"51":1471305600000,"52":1471392000000,"53":1486598400000,"54":1489968000000,"55":1490054400000,"56":1490140800000,"57":1490227200000,"58":1490313600000,"59":1492387200000,"60":1492473600000,"61":1492560000000,"62":1492646400000,"63":1492732800000,"64":1494201600000,"65":1494288000000,"66":1494374400000,"67":1494460800000,"68":1494547200000,"69":1502668800000,"70":1502755200000,"71":1502841600000,"72":1502928000000,"73":1503014400000,"74":1503100800000,"75":1503187200000,"76":1505174400000,"77":1505433600000,"78":1507507200000,"79":1507593600000,"80":1507680000000,"81":1507766400000,"82":1507852800000,"83":1507939200000,"84":1508025600000,"85":1508976000000,"86":1509062400000,"87":1509148800000,"88":1509235200000,"89":1509321600000,"90":1509408000000,"91":1512086400000,"92":1524268800000,"93":1524355200000,"94":1529884800000,"95":1529971200000,"96":1530057600000,"97":1530144000000,"98":1530230400000}}'
Update #2:
def get_academic_year(x):
if (x.month < 7):
year = x.year - 1
else:
year = x.year
return year
def get_week(x):
return int(((x['date'] - pd.to_datetime(pd.datetime(x['academic_year'], 7, 1)))).days / 7) + 1
rng = pd.date_range('7/1/2015', periods=365*3, freq='D')
df_x = pd.DataFrame()
df_x['date'] = rng
df_x['academic_year'] = df_x['date'].apply(lambda x: get_academic_year(x))
df_x['week'] = df_x.apply(lambda x: get_week(x), axis=1)
df_x
This might work for you.
df = pd.DataFrame({'A': ['2017-07-05', '2017-07-21', '2017-07-22',
'2017-08-01','2017-08-15', '2017-08-30']})
df['A'] = pd.to_datetime(df['A'])
df['Week'] = df['A'].dt.week - pd.to_datetime('2017-07-01').week
# A Week
# 0 2017-07-05 1
# 1 2017-07-21 3
# 2 2017-07-22 3
# 3 2017-08-01 5
# 4 2017-08-15 7
# 5 2017-08-30 9

Python date function bugs

I am trying to create a function in python which will display the date. So I can see the program run, I have set one day to five seconds, so every five seconds it will become the next 'day' and it will print the date.
I know there is already an in-build function for displaying a date, however I am very new to python and I am trying to improve my skills (so excuse my poor coding.)
I have set the starting date to the first of January, 2000.
Here is my code:
import time
def showDate():
year = 00
month = 1
day = 1
oneDay = 5
longMonths = [1, 3, 5, 7, 8, 10, 12]
shortMonths = [4, 6, 9, 11]
while True:
time.sleep(1)
oneDay = oneDay - 1
if oneDay == 0:
if month in longMonths:
if day > 31:
day = day + 1
else:
month = month + 1
day = 0
if month == 2:
if day > 28:
day = day + 1
else:
month = month + 1
day = 0
if month in shortMonths:
if day > 30:
day = day + 1
else:
month = month + 1
day = 0
if day == 31 and month == 12:
year = year + 1
print(str(day) + '/' + str(month) + '/' + str(year))
oneDay = 5
showDate()
However, when I try to run the program this is the output I get this:
>>>
0/3/0
0/5/0
0/7/0
0/8/0
0/10/0
0/12/0
0/13/0
0/13/0
0/13/0
I don't know why this is happening, could someone please suggest a solution?
There's no possible path through your code where day gets incremented.
I think you are actually confused between > and <: you check if day is greater than 31 or 28, which it never is. I think you mean if day < 31: and so on.
First of all, it's easier to just set time.sleep(5) instead of looping over time.sleep(1) 5 times. It's better to have a list of values with days of the month, not just 2 lists of the long and short months. Also your while loop is currently indefinite, is that intentional?
Anyway, your main problem was comparing day > 31, but there's lots of things that can be improved. As I said, I'm removing the use of oneDay to just do sleep(5) as it's cleaner and having one daysInMonths list.
import time
def showDate():
year = 00
month = 1
day = 1
daysInMonths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Now you can have only one if check about if the day has reached the end of a month, like this:
while True:
time.sleep(5)
if day < daysInMonths[month-1]:
day += 1
This will check the index of the list for the current month. It uses -1 because lists begin at index 0, and your months begin at 1. (ie. the months run from 1-12 but the list's indices are 0-11). Also I used the += operator, which is basically short hand for var = var + something. It works the same and looks neater.
This test encompasses all months, and then the alternative scenario is that you need to increment the month. I recommend in this block that you first check if the month is 12 and then increment the year from there. Also you should be setting day and month back to 1, since that was their starting value. If it's not the end of the year, increment the month and set day back to 1.
else:
if month == 12:
year += 1
day = 1
month = 1
else:
month += 1
day = 1
print("{}/{}/{}".format(day, month, year))
I also used the string.format syntax for neatness. With format, it will substitute the variables you pass in for {} in the string. It makes it easier to lay out how the string should actually look, and it converts the variables to string format implicitly.
Try this.
The day comparisons should be <, not >. When going to the next month, I set the day to 1, because there are no days 0 in the calendar. And I use elif for the subsequent month tests, because all the cases are exclusive.
def showDate():
year = 00
month = 1
day = 1
oneDay = 5
longMonths = [1, 3, 5, 7, 8, 10, 12]
shortMonths = [4, 6, 9, 11]
while True:
time.sleep(1)
oneDay = oneDay - 1
if oneDay == 0:
if month in longMonths:
if day < 31:
day = day + 1
else:
month = month + 1
day = 1
elif month == 2:
if day < 28:
day = day + 1
else:
month = month + 1
day = 1
if month in shortMonths:
if day < 30:
day = day + 1
else:
month = month + 1
day = 1
if day == 31 and month == 12:
year = year + 1
month = 1
print(str(day) + '/' + str(month) + '/' + str(year))
oneDay = 5

Python: How to get difference of 2 dates in HH:MM format?

I have 2 datetime objects:
a
datetime.datetime(2013,2,11,15,35)
b
datetime.datetime(2013,2,11,18,55)
The difference is 3:20
How can I obtain this in python?
I do:
(b-a).seconds/3600
But I get 3 instead of 3:20
Is manual construction acceptable? If you subtract the two datetimes you'll get a timedelta object. Then just grab the values from that:
>>> diff = b - a
>>> diff
datetime.timedelta(0, 12000)
>>> hrs = diff.seconds / 3600
>>> hrs
3
>>> mins = diff.seconds % 3600 / 60
>>> mins
20
>>> "%s:%s" % (hrs, mins)
'3:20'
>>> diff = b - a
>>> diff
datetime.timedelta(0, 12000)
>>> (datetime.datetime(2010, 1, 1, 0, 0, 0) + diff).strftime("%H:%M")
'03:20'
could be also a way to go.
maybe i think the hours is :
(b-a).days*24 +(b-a).seconds/3600
here it is another way:
x = (b-a).seconds/3600.0 + (b-a).days*24
hours = int(x)
mins = int((x - hours)*60)

Categories

Resources