Changing month_id when looping over dates in python - 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()

Related

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})

Retrieve indices of specific date

I am trying to retrieve the indices corresponding to a specific month for my data set.
This is for keeping track of the index lines for training a Neural Network after the train-test data split. I want to know for which dates my predictions correspond to.
I have tried the following in which i retrieve the indices corresponding to a specific day. Is there a way to have an argument like * in the day so i retrieve 1 whole month
target_date = pd.to_datetime('2013-10-24').date()
metadata.loc[metadata.Starttime.dt.date == target_date, :].index.values
which gives
array([0, 1], dtype=int64)
I would expect something like:
array([10, 14, 17], dtype=int64)
Where 10,14,17 are the indices corresponding to the month i searched for, not a specific day
Example:
installation = range(0,5)
equipment = range(0,5)
tag_name = range(0,5)
start_time = ['2013-10-15 02:30:24.670', '2013-9-15 02:30:24.670', '2013-8-15 02:30:24.670', '2013-7-15 02:30:24.670', '2013-6-15 02:30:24.670']
dic = {'Installation':installation,'Equipment':equipment,'Tag name':tag_name,'Starttime':start_time,}
metadata = pd.DataFrame(dic) #Create the dataframe
metadata['Starttime'] = pd.to_datetime(metadata['Starttime'])
target_date = pd.to_datetime('2013-10-15').date()
metadata.loc[metadata.Starttime.dt.date == target_date, :].index.values
You can just change your filtering condition to get the whole month:
metadata.loc[
(metadata.Starttime.dt.month == 10) &
(metadata.Starttime.dt.year == 2013)
].index.values
I think you need compare month peiod created by Series.dt.to_period for column and for scalar Timestamp.to_period:
installation = range(0,5)
equipment = range(0,5)
tag_name = range(0,5)
#change first 3 datetimes for same months
start_time = ['2013-10-15 02:30:24.670', '2013-10-16 02:30:24.670', '2013-10-17 02:30:24.670',
'2013-7-15 02:30:24.670', '2013-6-15 02:30:24.670']
dic = {'Installation':installation,'Equipment':equipment,
'Tag name':tag_name,'Starttime':start_time}
metadata = pd.DataFrame(dic) #Create the dataframe
metadata['Starttime'] = pd.to_datetime(metadata['Starttime'])
print (metadata)
Installation Equipment Tag name Starttime
0 0 0 0 2013-10-15 02:30:24.670
1 1 1 1 2013-10-16 02:30:24.670
2 2 2 2 2013-10-17 02:30:24.670
3 3 3 3 2013-07-15 02:30:24.670
4 4 4 4 2013-06-15 02:30:24.670
target_date = pd.to_datetime('2013-10-15').to_period('m')
idx = metadata.loc[metadata.Starttime.dt.to_period('m') == target_date].index.values
print (idx)
[0 1 2]

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

How do I perform timedelta and date comparison in Ruby?

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

Categories

Resources