I have two pairs of date data:
date_pair1 = [datetime.datetime(2021,3,1) , datetime.datetime(2020,2,1)]
date_pair2 = [datetime.datetime(2021,4,1) , datetime.datetime(2021,3,1)]
With Python:
delta1 = (date_pair1[0]-date_pair1[1]).days
delta2 = (date_pair2[0]-date_pair2[1]).days
year = 365
month = 30
age1 = f"{delta1//365} year {(delta1%365)//30} month {(delta1%365)%30} day"
age2 = f"{delta2//365} year {(delta2%365)//30} month {(delta2%365)%30} day"
print(age1,"-",age2)
Result:
1 year 0 month 29 day - 0 year 1 month 1 day
With Excel:
E5 cell:1.02.2020 F5 cell:1.03.2021
E6 cell:1.03.2021 F6 cell:1.04.2021
Using DATEDIF function:
=CONCAT(DATEDIF(E5,F5,"Y")," year ",DATEDIF(E5,F5,"YM")," month ",DATEDIF(E5,F5,"MD")," day")
=CONCAT(DATEDIF(E6,F6,"Y")," year ",DATEDIF(E6,F6,"YM")," month ",DATEDIF(E6,F6,"MD")," day")
1 year 1 month 0 day - 0 year 1 month 0 day
How can I get the results in Excel using python?
Use relativedelta
date_pair1 = [datetime.datetime(2021,3,1) , datetime.datetime(2020,2,1)]
date_pair2 = [datetime.datetime(2021,4,1) , datetime.datetime(2021,3,1)]
from dateutil.relativedelta import relativedelta
delta1 = relativedelta(date_pair1[0],date_pair1[1])
delta2 = relativedelta(date_pair2[0],date_pair2[1])
age1 = f"{delta1.years} year {delta1.months} month {delta1.days} day"
age2 = f"{delta2.years} year {delta2.months} month {delta2.days} day"
print(age1,"-",age2)
Related
I have the following data:
Year&Week
Year
Week
2022-50
2022
50
2022-51
2022
51
2022-52
2022
52
I would like to convert that information by adding a new column that reflects the last day (sunday) and the initial day (monday) of the weeks. So my final dataframe should looks like the following:
Year&Week
Year
Week
Initial day of week
Last day of week
2022-50
2022
50
12/Dec/2022
18/Dec/2022
2022-51
2022
51
19/Dec/2022
25/Dec/2022
2022-52
2022
52
26/Dec/2022
01/Jan/2023
We can use pd.to_datetime and create date base:
%W: The week number of the year
%Y: The year number
%a: Weekday, short version
%b: The first three characters of the month name
%d: The day of the month
df['Initial day of week'] = pd.to_datetime(
df['Week'].astype(str) + df['Year'].astype(str) + 'Mon', format='%W%Y%a'
).dt.strftime("%d/%b/%Y")
df['Last day of week'] = pd.to_datetime(
df['Week'].astype(str) + df['Year'].astype(str) + 'Sun', format='%W%Y%a'
).dt.strftime("%d/%b/%Y")
print(df)
Output:
Year&Week Year Week Initial day of week Last day of week
0 2022-50 2022 50 12/Dec/2022 18/Dec/2022
1 2022-51 2022 51 19/Dec/2022 25/Dec/2022
2 2022-52 2022 52 26/Dec/2022 01/Jan/2023
You can use the python datetime module to convert 2022-50 which is probably is in the "%Y%W" Format to M/d/y format, like the below's peace of codes:
from datetime import datetime
input_date = "2022-50"
right_date = datetime.strptime(input_date, "%Y-%W")
formate_date_reult = right_date.strftime("%m/%d/%Y")
print(formate_date_reult) # Output is: 12/25/2022
Using Python...
How can I select all of the Sundays (or any day for that matter) in a year?
[ '01/03/2010','01/10/2010','01/17/2010','01/24/2010', ...]
These dates represent the Sundays for 2010. This could also apply to any day of the week I suppose.
You can use date from the datetime module to find the first Sunday in a year and then keep adding seven days, generating new Sundays:
from datetime import date, timedelta
def allsundays(year):
d = date(year, 1, 1) # January 1st
d += timedelta(days = 6 - d.weekday()) # First Sunday
while d.year == year:
yield d
d += timedelta(days = 7)
for d in allsundays(2010):
print(d)
Pandas has great functionality for this purpose with its date_range() function.
The result is a pandas DatetimeIndex, but can be converted to a list easily.
import pandas as pd
def allsundays(year):
return pd.date_range(start=str(year), end=str(year+1),
freq='W-SUN').strftime('%m/%d/%Y').tolist()
allsundays(2017)[:5] # First 5 Sundays of 2017
# ['01/01/2017', '01/08/2017', '01/15/2017', '01/22/2017', '01/29/2017']
Using the dateutil module, you could generate the list this way:
#!/usr/bin/env python
import dateutil.relativedelta as relativedelta
import dateutil.rrule as rrule
import datetime
year=2010
before=datetime.datetime(year,1,1)
after=datetime.datetime(year,12,31)
rr = rrule.rrule(rrule.WEEKLY,byweekday=relativedelta.SU,dtstart=before)
print rr.between(before,after,inc=True)
Although finding all Sundays is not too hard to do without dateutil, the module is handy especially if you have more complicated or varied date calculations.
If you are using Debian/Ubuntu, dateutil is provided by the python-dateutil package.
from datetime import date, timedelta
from typing import List
def find_sundays_between(start: date, end: date) -> List[date]:
total_days: int = (end - start).days + 1
sunday: int = 6
all_days = [start + timedelta(days=day) for day in range(total_days)]
return [day for day in all_days if day.weekday() is sunday]
date_start: date = date(2018, 1, 1)
date_end: date = date(2018, 12, 31)
sundays = find_sundays_between(date_start, date_end)
If looking for a more general approach (ie not only Sundays), we can build on sth's answer:
def weeknum(dayname):
if dayname == 'Monday': return 0
if dayname == 'Tuesday': return 1
if dayname == 'Wednesday':return 2
if dayname == 'Thursday': return 3
if dayname == 'Friday': return 4
if dayname == 'Saturday': return 5
if dayname == 'Sunday': return 6
This will translate the name of the day into an int.
Then do:
from datetime import date, timedelta
def alldays(year, whichDayYouWant):
d = date(year, 1, 1)
d += timedelta(days = (weeknum(whichDayYouWant) - d.weekday()) % 7)
while d.year == year:
yield d
d += timedelta(days = 7)
for d in alldays(2020,'Sunday'):
print(d)
Note the presence of % 7 in alldays(). This outputs:
2020-01-05
2020-01-12
2020-01-19
2020-01-26
2020-02-02
2020-02-09
2020-02-16
...
Can also do:
for d in alldays(2020,'Friday'):
print(d)
which will give you:
2020-01-03
2020-01-10
2020-01-17
2020-01-24
2020-01-31
2020-02-07
2020-02-14
...
You can iterate over a calendar for that year.
The below should return all Tuesdays and Thursdays for a given year.
# Returns all Tuesdays and Thursdays of a given year
from datetime import date
import calendar
year = 2016
c = calendar.TextCalendar(calendar.SUNDAY)
for m in range(1,13):
for i in c.itermonthdays(year,m):
if i != 0: #calendar constructs months with leading zeros (days belongng to the previous month)
day = date(year,m,i)
if day.weekday() == 1 or day.weekday() == 3: #if its Tuesday or Thursday
print "%s-%s-%s" % (year,m,i)
import time
from datetime import timedelta, datetime
first_date = '2021-01-01'
final_date = '2021-12-31'
first_date = datetime.strptime(first_date, '%Y-%m-%d')
last_date = datetime.strptime(final_date, '%Y-%m-%d')
week_day = 'Sunday'
dates = [first_date + timedelta(days=x) for x in range((last_date - first_date).days + 1) if (first_date + timedelta(days=x)).weekday() == time.strptime(week_day, '%A').tm_wday]
It will return all Sunday date of given date range.
Here's a complete generator function that builds on the solution from #sth. It includes the crucial fix that was mentioned in his solution's comments.
You can specify the day of week (using Python's indexing with 0=Monday to 6=Sunday), the starting date, and the number of weeks to enumerate.
def get_all_dates_of_day_of_week_in_year(day_of_week, start_year, start_month,
start_day, max_weeks=None):
'''
Generator function to enumerate all calendar dates for a specific day
of the week during one year. For example, all Wednesdays in 2018 are:
1/3/2018, 1/10/2018, 1/17/2018, 1/24/2018, 1/31/2018, 2/7/2018, etc.
Parameters:
----------
day_of_week : int
The day_of_week should be one of these values: 0=Monday, 1=Tuesday,
2=Wednesday, 3=Thursday, 4=Friday, 5=Saturday, 6=Sunday.
start_year : int
start_month : int
start_day : int
The starting date from which to list out all the dates
max_weeks : int or None
If None, then list out all dates for the rest of the year.
Otherwise, end the list after max_weeks number of weeks.
'''
if day_of_week < 0 or day_of_week > 6:
raise ValueError('day_of_week should be in [0, 6]')
date_iter = date(start_year, start_month, start_day)
# First desired day_of_week
date_iter += timedelta(days=(day_of_week - date_iter.weekday() + 7) % 7)
week = 1
while date_iter.year == start_year:
yield date_iter
date_iter += timedelta(days=7)
if max_weeks is not None:
week += 1
if week > max_weeks:
break
Example usage to get all Wednesdays starting on January 1, 2018, for 10 weeks.
import calendar
day_of_week = 2
max_weeks = 10
for d in get_all_dates_of_day_of_week_in_year (day_of_week, 2018, 1, 1, max_weeks):
print "%s, %d/%d/%d" % (calendar.day_name[d.weekday()], d.year, d.month, d.day)
The above code produces:
Wednesday, 2018/1/3
Wednesday, 2018/1/10
Wednesday, 2018/1/17
Wednesday, 2018/1/24
Wednesday, 2018/1/31
Wednesday, 2018/2/7
Wednesday, 2018/2/14
Wednesday, 2018/2/21
Wednesday, 2018/2/28
Wednesday, 2018/3/7
according to #sth answer I like to give you an alternative without a function
from datetime import date, timedelta,datetime
sunndays = list()
year_var = datetime.now() #get current date
year_var = year_var.year #get only the year
d = date(year_var, 1, 1) #get the 01.01 of the current year = 01.01.2020
#now we have to skip 4 days to get to sunday.
#d.weekday is wednesday so it has a value of 2
d += timedelta(days=6 - d.weekday()) # 01.01.2020 + 4 days (6-2=4)
sunndays.append(str(d.strftime('%d-%m-%Y'))) #you need to catch the first sunday
#here you get every other sundays
while d.year == year_var:
d += timedelta(days=7)
sunndays.append(str(d.strftime('%d-%m-%Y')))
print(sunndays) # only for control
if you want every monday for example
#for 2021 the 01.01 is a friday the value is 4
#we need to skip 3 days 7-4 = 3
d += timedelta(days=7 - d.weekday())
according to #sth answer,it will lost the day when 1st is sunday.This will be better:
d = datetime.date(year, month-1, 28)
for _ in range(5):
d = d + datetime.timedelta(days=-d.weekday(), weeks=1)
if d.month!=month:
break
date.append(d)
I'm teaching myself python to ATBS. Instead of spending 45 minutes typing out a bunch of repetitive data in excel I've spent the past 90 failing to write a simple calendar script.
Starting with the values "2012-09-01" and "2012-09-30" I want to each line to increase the month value by 1 it hits 12 and at which point the year value advances by 1, until the date 2018-12-31.
e.g.
"2012-09-01 2012-09-30
2012-10-01 2012-10-31
2012-11-01 2012-11-30
2012-12-01 2012-12-31"
Here's my code, which stops at 2012-12-31.
import datetime
year = 2012
month = 9
day_start = 1
day_end = 31
while year <= 2018:
while month <= 12:
if month == 4 or month == 6 or month == 9 or month == 11:
day_end = 30
else:
day_end = 31
print(datetime.date(year, month, day_start), " ", datetime.date(year, month, day_end))
month = month + 1
year = year + 1
Any help is much appreciated!
Check this out. Using the calendar library to detect leap years.
import datetime
import calendar
year = 2012
month = 9
day_start = 1
day_end = 31
while year <= 2018:
while month <= 12:
if month == 4 or month == 6 or month == 9 or month == 11:
day_end = 30
elif month == 2:
day_end = 29 if calendar.isleap(year) else 28
else:
day_end = 31
print(datetime.date(year, month, day_start), " ", datetime.date(year, month, day_end))
month = month + 1
year = year + 1
month = 1
Line
if month == 4 or month == 6 or month == 9 or month == 11:
can be abbreviated to:
if month in (4, 6, 9, 11):
Here's my data
Customer_id Date-of-birth
1 1992-07-02
2 1991-07-03
Here's my code
import datetime as dt
df['now'] = dt.datetime.now()
df['age'] = df['now'].dt.date - df['Date-of-birth']
Here's the result
Customer_id Date-of-birth age
1 1992-07-02 xxxx days
2 1991-07-03 xxxx days
The result that I want is
Customer_id Date-of-birth age
1 1992-07-02 26 years 22 days
2 1991-07-03 27 years 21 days
Just let you now, by df.dtypes, Date-of-birth is an object because is based on customer input in dropdown
How can I achieve this? I hope the question is clear enough
Use this solution with custom function, because count it is not easy because leaps years:
from dateutil.relativedelta import relativedelta
def f(end):
r = relativedelta(pd.to_datetime('now'), end)
return '{} years {} days'.format(r.years, r.days)
df['age'] = df["Date-of-birth"].apply(f)
print (df)
Customer_id Date-of-birth age
0 1 1992-07-02 26 years 22 days
1 2 1991-07-03 27 years 21 days
Input:
import pandas as pd
import datetime as dt
now = dt.datetime.now()
for i in range(0, len(df)):
diff = now - dt.datetime.strptime(df['Date-of-Birth'][i], '%Y-%m-%d')
years = diff.days // 365
days = diff.days - (years*365)
df['age'][i] = str(years) + ' years ' + str(days) + ' days'
print(df)
Output:
Customer_id Date-of-Birth age
1 1992-07-04 26 years 25 days
2 1991-07-04 27 years 26 days
Maybe you could use something like the following. Note that it relies on the fact that the average year has 365.25 days, so it may be a day off sometimes.
import datetime as dt
def year_days_diff(x):
diff = (dt.datetime.now() - x).days
return str(int(diff / 365.25)) + ' years ' + str(int(diff / 365.25 % 1 * 365.25)) + ' days'
Example:
birth_date = dt.datetime.now() - dt.timedelta(10000)
year_days_diff(birth_date)
output:
'27 years 138 days'
This could give you age by rounding to years.
ref_date = dt.datetime.now()
df['age'] = df['Date-of-birth'].apply(lambda x: len(pd.date_range(start = x, end = ref_date, freq = 'Y')))
Use astype('<m8[Y]')
Ex:
df['age'] = (pd.to_datetime('now') - df['Date-of-birth']).astype('<m8[Y]')
Demo:
import pandas as pd
df = pd.DataFrame({"Date-of-birth": pd.to_datetime(['1992-07-24', '1991-07-24'])})
df["age"] = (pd.to_datetime('now') - df["Date-of-birth"]).astype('<m8[Y]')
print(df)
Output:
Date-of-birth age
0 1992-07-24 25.0
1 1991-07-24 27.0
Using Python...
How can I select all of the Sundays (or any day for that matter) in a year?
[ '01/03/2010','01/10/2010','01/17/2010','01/24/2010', ...]
These dates represent the Sundays for 2010. This could also apply to any day of the week I suppose.
You can use date from the datetime module to find the first Sunday in a year and then keep adding seven days, generating new Sundays:
from datetime import date, timedelta
def allsundays(year):
d = date(year, 1, 1) # January 1st
d += timedelta(days = 6 - d.weekday()) # First Sunday
while d.year == year:
yield d
d += timedelta(days = 7)
for d in allsundays(2010):
print(d)
Pandas has great functionality for this purpose with its date_range() function.
The result is a pandas DatetimeIndex, but can be converted to a list easily.
import pandas as pd
def allsundays(year):
return pd.date_range(start=str(year), end=str(year+1),
freq='W-SUN').strftime('%m/%d/%Y').tolist()
allsundays(2017)[:5] # First 5 Sundays of 2017
# ['01/01/2017', '01/08/2017', '01/15/2017', '01/22/2017', '01/29/2017']
Using the dateutil module, you could generate the list this way:
#!/usr/bin/env python
import dateutil.relativedelta as relativedelta
import dateutil.rrule as rrule
import datetime
year=2010
before=datetime.datetime(year,1,1)
after=datetime.datetime(year,12,31)
rr = rrule.rrule(rrule.WEEKLY,byweekday=relativedelta.SU,dtstart=before)
print rr.between(before,after,inc=True)
Although finding all Sundays is not too hard to do without dateutil, the module is handy especially if you have more complicated or varied date calculations.
If you are using Debian/Ubuntu, dateutil is provided by the python-dateutil package.
from datetime import date, timedelta
from typing import List
def find_sundays_between(start: date, end: date) -> List[date]:
total_days: int = (end - start).days + 1
sunday: int = 6
all_days = [start + timedelta(days=day) for day in range(total_days)]
return [day for day in all_days if day.weekday() is sunday]
date_start: date = date(2018, 1, 1)
date_end: date = date(2018, 12, 31)
sundays = find_sundays_between(date_start, date_end)
If looking for a more general approach (ie not only Sundays), we can build on sth's answer:
def weeknum(dayname):
if dayname == 'Monday': return 0
if dayname == 'Tuesday': return 1
if dayname == 'Wednesday':return 2
if dayname == 'Thursday': return 3
if dayname == 'Friday': return 4
if dayname == 'Saturday': return 5
if dayname == 'Sunday': return 6
This will translate the name of the day into an int.
Then do:
from datetime import date, timedelta
def alldays(year, whichDayYouWant):
d = date(year, 1, 1)
d += timedelta(days = (weeknum(whichDayYouWant) - d.weekday()) % 7)
while d.year == year:
yield d
d += timedelta(days = 7)
for d in alldays(2020,'Sunday'):
print(d)
Note the presence of % 7 in alldays(). This outputs:
2020-01-05
2020-01-12
2020-01-19
2020-01-26
2020-02-02
2020-02-09
2020-02-16
...
Can also do:
for d in alldays(2020,'Friday'):
print(d)
which will give you:
2020-01-03
2020-01-10
2020-01-17
2020-01-24
2020-01-31
2020-02-07
2020-02-14
...
You can iterate over a calendar for that year.
The below should return all Tuesdays and Thursdays for a given year.
# Returns all Tuesdays and Thursdays of a given year
from datetime import date
import calendar
year = 2016
c = calendar.TextCalendar(calendar.SUNDAY)
for m in range(1,13):
for i in c.itermonthdays(year,m):
if i != 0: #calendar constructs months with leading zeros (days belongng to the previous month)
day = date(year,m,i)
if day.weekday() == 1 or day.weekday() == 3: #if its Tuesday or Thursday
print "%s-%s-%s" % (year,m,i)
import time
from datetime import timedelta, datetime
first_date = '2021-01-01'
final_date = '2021-12-31'
first_date = datetime.strptime(first_date, '%Y-%m-%d')
last_date = datetime.strptime(final_date, '%Y-%m-%d')
week_day = 'Sunday'
dates = [first_date + timedelta(days=x) for x in range((last_date - first_date).days + 1) if (first_date + timedelta(days=x)).weekday() == time.strptime(week_day, '%A').tm_wday]
It will return all Sunday date of given date range.
Here's a complete generator function that builds on the solution from #sth. It includes the crucial fix that was mentioned in his solution's comments.
You can specify the day of week (using Python's indexing with 0=Monday to 6=Sunday), the starting date, and the number of weeks to enumerate.
def get_all_dates_of_day_of_week_in_year(day_of_week, start_year, start_month,
start_day, max_weeks=None):
'''
Generator function to enumerate all calendar dates for a specific day
of the week during one year. For example, all Wednesdays in 2018 are:
1/3/2018, 1/10/2018, 1/17/2018, 1/24/2018, 1/31/2018, 2/7/2018, etc.
Parameters:
----------
day_of_week : int
The day_of_week should be one of these values: 0=Monday, 1=Tuesday,
2=Wednesday, 3=Thursday, 4=Friday, 5=Saturday, 6=Sunday.
start_year : int
start_month : int
start_day : int
The starting date from which to list out all the dates
max_weeks : int or None
If None, then list out all dates for the rest of the year.
Otherwise, end the list after max_weeks number of weeks.
'''
if day_of_week < 0 or day_of_week > 6:
raise ValueError('day_of_week should be in [0, 6]')
date_iter = date(start_year, start_month, start_day)
# First desired day_of_week
date_iter += timedelta(days=(day_of_week - date_iter.weekday() + 7) % 7)
week = 1
while date_iter.year == start_year:
yield date_iter
date_iter += timedelta(days=7)
if max_weeks is not None:
week += 1
if week > max_weeks:
break
Example usage to get all Wednesdays starting on January 1, 2018, for 10 weeks.
import calendar
day_of_week = 2
max_weeks = 10
for d in get_all_dates_of_day_of_week_in_year (day_of_week, 2018, 1, 1, max_weeks):
print "%s, %d/%d/%d" % (calendar.day_name[d.weekday()], d.year, d.month, d.day)
The above code produces:
Wednesday, 2018/1/3
Wednesday, 2018/1/10
Wednesday, 2018/1/17
Wednesday, 2018/1/24
Wednesday, 2018/1/31
Wednesday, 2018/2/7
Wednesday, 2018/2/14
Wednesday, 2018/2/21
Wednesday, 2018/2/28
Wednesday, 2018/3/7
according to #sth answer I like to give you an alternative without a function
from datetime import date, timedelta,datetime
sunndays = list()
year_var = datetime.now() #get current date
year_var = year_var.year #get only the year
d = date(year_var, 1, 1) #get the 01.01 of the current year = 01.01.2020
#now we have to skip 4 days to get to sunday.
#d.weekday is wednesday so it has a value of 2
d += timedelta(days=6 - d.weekday()) # 01.01.2020 + 4 days (6-2=4)
sunndays.append(str(d.strftime('%d-%m-%Y'))) #you need to catch the first sunday
#here you get every other sundays
while d.year == year_var:
d += timedelta(days=7)
sunndays.append(str(d.strftime('%d-%m-%Y')))
print(sunndays) # only for control
if you want every monday for example
#for 2021 the 01.01 is a friday the value is 4
#we need to skip 3 days 7-4 = 3
d += timedelta(days=7 - d.weekday())
according to #sth answer,it will lost the day when 1st is sunday.This will be better:
d = datetime.date(year, month-1, 28)
for _ in range(5):
d = d + datetime.timedelta(days=-d.weekday(), weeks=1)
if d.month!=month:
break
date.append(d)