Python Best Syntactic way of Calculating the age based on datetime - python-3.x

After searching around the web got the below two ways to get the age of a person.
Just curious to Know if there is better synthetic way of calculating & writing it in 3.x version of python.
First way around ...
$ cat birth1.py
#!/grid/common/pkgs/python/v3.6.1/bin/python3
import datetime
year = datetime.datetime.now().year # getting current year from the system
year_of_birth = int(input("Enter Your Birth Year: "))
print("You are %i Year Old" % (year - year_of_birth))
The Result produced..
$ ./birth1.py
Enter Your Birth Year: 1981
You are 37 Year Old
Second way around ....
$ cat birth2.py
#!/grid/common/pkgs/python/v3.6.1/bin/python3
from datetime import datetime, date
print("Your date of birth (dd/mm/yyyy)")
date_of_birth = datetime.strptime(input("Please Put your age here: "), "%d/%m/%Y")
def calculate_age(born):
today = date.today()
return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
age = calculate_age(date_of_birth)
print("You are %i Year Old." % (age))
The Result produces..
$ ./birth2.py
Your date of birth (dd/mm/yyyy)
Please Put your age here: 22/09/2015
You are 2 Year Old.

Take advantage of timedelta.
import datetime as dt
def years_ago(start: str):
sec_per_year = 365.24 * 24 * 60 * 60
delta = dt.datetime.now() - dt.datetime.strptime(start, '%d/%m/%Y')
return delta.total_seconds() / sec_per_year
if __name__ == '__main__':
print(int(years_ago(input('What is your date of birth (dd/mm/yyyy) ? '))))

Related

Generating a date in a particular format using python

I have a python code that looks like this. I am receiving the values
of year, month and day in form of a string. I will test whether they are not null.
If they are not null I will like to generate a date in this format MMddyyyy from the variables
from datetime import datetime
year = "2022"
month = "7"
day = "15"
if len(year) and len(month) and len(day):
print('variables are not empty')
#prepare = "{month}/{day}/{year}"
#valueDt = datetime.strptime(prepare,"%m/%d/%Y")
else:
print('variables are empty')
The solution I have is not working. How can I generate this date?
It should work without calling len as well.
from datetime import datetime, date
year = "2022"
month = "7"
day = "15"
if year and month and day:
print('variables are not empty')
prepare = date(int(year), int(month), int(day))
valueDt = datetime.strftime(prepare, "%m/%d/%Y")
print(valueDt)
else:
print('variables are empty')
from datetime import datetime, date
year = "2022"
month = "7"
day = "15"
if len(year) and len(month) and len(day):
print('variables are not empty')
prepare = date(int(year), int(month), int(day))
valueDt = datetime.strftime(prepare, "%m/%d/%Y")
print(valueDt)
else:
print('variables are empty')

How do I loop through days in months in python3?

Say for the year of 2020, how do I iterate through the days in the months so that my outcome would be in the following format:
Jan1
Jan2
Jan3
....
Jan31
Feb1
I've tried so many things online but I couldnt find an answer. Please help :(
Both of these methods will handle leap years correctly out of the box.
Using a simple while loop:
from datetime import datetime, timedelta
def iter_days(year):
dt = datetime(year, 1, 1)
while dt.year == year:
yield dt
dt += timedelta(days=1)
Using date rules:
from datetime import datetime
from dateutil.rrule import rrule, DAILY
def iter_days(year):
first_date = datetime(year, 1, 1)
last_date = datetime(year, 12, 31)
return rrule(DAILY, dtstart=first_date, until=last_date)
Both would be used the same:
for dt in iter_days(2020):
print(dt.strftime('%b%-d'))
The format string '%b%-d' will give you the format you specified in your question. I don't know if that was a requirement or not.
This is crude but gets what you want for 2020. You'll need to change 366 to 365 for non-leap-years.
#!/usr/bin/python3
import datetime
startDate = '2020-01-01'
start = datetime.datetime.strptime(startDate, '%Y-%m-%d')
for dayNum in range(0,366):
dayOfYear = start + datetime.timedelta(days=dayNum)
print(dayOfYear.strftime('%b %d, %Y'))
The calendar module offers quite a bit of functionality.
Here is a solution that works for any given year
import calendar as cal
for mi in range(1,13):
_, days = cal.monthrange(2020, mi)
for d in range(1, days+1):
print(cal.month_name[mi], d)

Convert dates to specific format

I have a pandas dataframe that looks like:
import pandas as pd
df1 = pd.DataFrame({'Counterparty':['Bank','Client','Bank','Bank','Bank','Bank'],
'Date':['4Q18','1Q19','2Q19','4Q21','FY22','H123']
})
I want to convert the 'Date' column from a string to a date such that the date is the last date for that particular period. ie 'FQ18'= 31st Dec 2018, '1Q19' = 31st Mar 2019, 'FY22' = 31st Dec 2022,'H123'= 30th June 2023
Any suggestions how to achieve this ?
As mentioned by #jpp, you're going to have to do some customization. There isn't existing functionality to map "FY22" to 2022-12-31, to my knowledge. Here's something to get you started, based on the limited example you've shown:
import re
import pandas as pd
from pandas.core.tools.datetimes import DateParseError
from pandas.tseries import offsets
halfyr = re.compile(r'H(?P<half>\d)(?P<year>\d{2})')
fiscalyr = re.compile(r'FY(?P<year>\d{2})')
def try_qend(date):
try:
return pd.to_datetime(date) + offsets.QuarterEnd()
except (DateParseError, ValueError):
halfyr_match = halfyr.match(date)
if halfyr_match:
half, year = [int(i) for i in halfyr_match.groups()]
month = 6 if half == 1 else 12
return pd.datetime(2000 + year, month, 1) + offsets.MonthEnd()
else:
fiscalyr_match = fiscalyr.match(date)
if fiscalyr_match:
year = int(fiscalyr_match.group('year'))
return pd.datetime(2000 + year, 12, 31)
else:
# You're SOL
return pd.NaT
def parse_dates(dates):
return pd.to_datetime([try_qend(date) for date in dates])
Assumptions:
All years are 20yy, not 19xx.
The regex patterns here completely describe the year-half/fiscal-year syntax set.
Example:
dates = ['4Q18','1Q19','2Q19','4Q21','FY22','H123']
parse_dates(dates)
DatetimeIndex(['2018-12-31', '2019-03-31', '2019-06-30', '2021-12-31',
'2022-12-31', '2023-06-30'],
dtype='datetime64[ns]', freq=None)

python3 iterating through dates

I have a list of date objects X ("%Y,%m,%d") and a date Y and want to have a list Z with all dates in it that are +-10days away from date Y IGNORING the year.
Ex.:
timeDelta = 10days
X = [2017-10-10, 2014-09-31, 1999-05-10, 1992-10-18]
Y = 2019-10-05
Z = MyFunction(X, Y, delta)
MyFunction(X,Y, timeDelta):
for i in range((currentDate-500000),currentDate,10000): # last 50 years in 1 year steps
bottomBoundries.append(datetime.strptime(str(i),'%Y%m%d')-timedelta(timeDelta))
topBoundries.append(datetime.strptime(str(i),'%Y%m%d')+timedelta(timeDelta))
for i in range(0, pandas.shape[0], 1):
for j in range(0, len(bottomBoundries) , 1):
if ((pandas["MESS_DATUM"].iloc[i] > bottomBoundries[j]) & (pandas["MESS_DATUM"].iloc[i] < topBoundries[j])):
indices.append(i)
result = pandas.iloc[indices]
return result
This takes a lot of time and I was wondering how to make it more efficient.
you could use the timetuple().yday to get the day in the year
so something like this might work:
def diff_without_year(date, reference_date, timedelta):
ref_yday = reference_date.timetuple().yday
diff = d.timetuple().yday - ref_yday # + optionally code to take care of the difference in hours, minutes,...
return abs(diff) <= timedelta
here timedelta is in days. If you get it in a TimeDelta object, you can convert by dividing by pd.TimeDelta('1day')
df['result'] = df["MESS_DATUM"].apply(lambda x: diff_without_year(x, ref_date, timedelta))
If you have your dates in a pandas series, you can simplify this up by using Series.dt.dayofyear
df['result'] = (df["MESS_DATUM"].dt.dayofyear - reference_date.timetuple().yday) < timedelta
A more adhoc solution that checks for each date in X whether the date in the year of Y is within 10 days, as well as the date in the preceding and succeeding year. This runs in linear time in size of X. For a large list of X, you can adapt this to do it in a pandas dataframe, and parallelize this code.
import datetime
timeDelta = 10 # in days
X = ['2017-10-10', '2014-09-30', '1999-05-10', '1992-10-18']
Y = '2019-10-05'
Y_date = datetime.datetime.strptime(Y, '%Y-%m-%d') # convert to datetime
td = datetime.timedelta(timeDelta)
year = Y_date.year
output_dates = []
for date in X:
X_date = datetime.datetime.strptime(date, '%Y-%m-%d')
month = X_date.month
day = X_date.day
date_previous_year = datetime.datetime(year=year-1, month=month, day=day)
date_current_year = datetime.datetime(year=year, month=month, day=day)
date_next_year = datetime.datetime(year=year+1, month=month, day=day)
if abs(date_previous_year - Y_date) <= td or \
abs(date_current_year - Y_date) <= td or \
abs(date_next_year - Y_date) <= td:
output_dates.append(date)
print(output_dates)

How to recursively ask for input when given wrong date format for two raw input and continue the operation in python

I'm trying to get two dates as input and convert is epoch time, but i need the two different dates given as input to be validated in correct format else recursively ask for correct input.
from datetime import date
import datetime
start_date = datetime.datetime.strptime(raw_input('Enter Start date in the format DD-MM-YYYY: '), '%d-%m-%Y')
end_date = datetime.datetime.strptime(raw_input('Enter Start date in the format DD-MM-YYYY: '), '%d-%m-%Y')
epoch_date = datetime.datetime(1970,1,1)
diff1 = (start_date - epoch_date).days
diff2 = (end_date - epoch_date).days
epoch1 = (diff1 * 86400)
epoch2 = (diff2 * 86400)
print('\nPTime_Start: %i' % diff1),
print("&"),
print('PTime_End: %i' % diff2)
print('Epoch_Start: %i' % epoch1),
print("&"),
print('Epoch_End: %i' % epoch2)
First of all, you are using Python 3.x and Python 3.x does not have any function that is called "raw_input()". It has been changed to "input()".
def take_date_input():
input_date = input('Enter date in the format DD-MM-YYYY: ')
try:
one_date = datetime.datetime.strptime(input_date, '%d-%m-%Y')
except ValueError:
return take_date_input()
return one_date
You can do this if you really want recursiveness in your code but it would be better with while loop.

Resources