How to find out week no of the month in python? - python

I have seen many ways to determine week of the year. Like by giving instruction datetime.date(2016, 2, 14).isocalendar()[1] I get 6 as output. Which means 14th feb 2016 falls under 6th Week of the year. But I couldn't find any way by which I could find week of the Month.
Means IF I give input as some_function(2016,2,16)
I should get output as 3, denoting me that 16th Feb 2016 is 3rd week of the Feb 2016
[ this is different question than similar available question, here I'm asking about finding week no of the month and not of the year]

This function did the work what I wanted
from math import ceil
def week_of_month(dt):
first_day = dt.replace(day=1)
dom = dt.day
adjusted_dom = dom + first_day.weekday()
return int(ceil(adjusted_dom/7.0))
I got this function from This StackOverFlow Answer

import datetime
def week_number_of_month(date_value):
week_number = (date_value.isocalendar()[1] - date_value.replace(day=1).isocalendar()[1] + 1)
if week_number == -46:
week_number = 6
return week_number
date_given = datetime.datetime(year=2018, month=12, day=31).date()
week_number_of_month(date_given)

Related

needed to extract the quarter from a given date

Problem 1
As an analyst, you had to present the quarterly performance results of your client. The data which you were provided was on daily basis. To complete this task, you needed to extract the quarter from a given date. For example:
if the date lies between 1st Jan, 2020 - 31st March, 2020, you need to extract the corresponding quarter as '2020-Q1'
if the date lies between 1st April, 2020 - 30th June, 2020, the extracted quarter will be '2020-Q2'
if the date lies between 1st July, 2020 - 30th September, 2020, the extracted quarter will be '2020-Q3'
if the date lies between 1st October, 2020 - 31st Decemeber, 2020 then the extracted quarter will be '2020-Q4'
Hi and welcome to stackoverflow. I'm sure that this answer to a similar question will certainly help you.
Here is a quick summary of the above answer. Basically, you just need to check what month a given date is from and convert it to a number (1 to 12). If you subtract 1 from this (so it runs from 0 for january to 11 for december) and devide this number by 3 using integer division you get the quarter information you are looking for in the format 0 to 3. If you just add 1 again you get the correct quarter you are looking for.
Or using python code taken from the answer I linked above:
def printQuarter(month):
print((month-1)//3 + 1)
printQuarter(1) # january, result: 1
printQuarter(4) # april, result: 2
printQuarter(12) # december, result: 4
Alternatively, you could of course use if-else statements to solve this problem, as you suggested with the if-statement tag in your question. This certainly works but is far less elegant. If for some reason you still want to do this, you could do e.g.:
if month <= 3:
print("Q1")
elif month <= 6:
print("Q2")
elif month <= 9:
print("Q3")
else:
print("Q4")
I had an answer framed for you some time back! Alas! SO was down :-) . You can use an approach for finding the quarter using month of the date itself. See below.
from datetime import datetime
_date_str = "1 April, 2020"
def get_quarter_str(date_str):
known_date = datetime.strptime(date_str, "%d %B, %Y")
quarter = ((known_date.month - 1) // 3) + 1
return f"{known_date.year} - Q{quarter}"
print(get_quarter_str(_date_str))
Define a dictionary with the 'limits' of each quarter. I would do something like this:
from datetime import date
quarters = {
'2020-Q1': ((2020, 1, 1), (2020, 3, 31)),
'2020-Q2': ((2020, 4, 1), (2020, 6, 30)),
'2020-Q3': ((2020, 7, 1), (2020, 9, 30)),
'2020-Q4': ((2020, 10, 1), (2020, 12, 31))
}
def get_quarter(my_date):
try:
if not isinstance(my_date, date): #Check if the input is a date
raise TypeError
for quarter, limits in quarters.items():
if date(*limits[0]) <= my_date <= date(*limits[1]):
return quarter
except TypeError:
... # Handle exception
def main():
my_date = date(2020, 4, 15) #Define a valid input
print(get_quarter(my_date)) #Run the function
if __name__ == '__main__':
main()
This example prints out:
'2020-Q2'
date_year = '2020'
date_month = '07'
if (date_month >= "01") & (date_month <="03"):
print("quarter = ", date_year + '-Q1')
elif (date_month >= "04") & (date_month <="06"):
print("quarter = ", date_year + '-Q2')
elif (date_month >= "07") & (date_month <="09"):
print("quarter = ", date_year + '-Q3')
else:
print("quarter = ", date_year + '-Q4')

Is the output week number string correct?

I'm trying to generate week number string using Python time module, considering week starts on Sunday.
If my interpretation of the official documentation is correct then this can be achieved by the following code:
import time
time.strftime("%U", time.localtime())
>> 37
My question is, is the above output correct? Shouldn't the output be 38 instead, considering the below details:
My timezone is IST (GMT+5:30)
import time
#Year
time.localtime()[0]
>> 2019
#Month
time.localtime()[1]
>> 9
#Day
time.localtime()[2]
>> 18
Yes, the output is correct. Week 1 started on January 6th, as that was the first Sunday in 2019. January 1st through 5th were week 0:
>>> time.strftime('%U', time.strptime("2019-1-1", "%Y-%m-%d"))
'00'
>>> time.strftime('%U', time.strptime("2019-1-6", "%Y-%m-%d"))
'01'
This is covered in the documentation:
All days in a new year preceding the first Sunday are considered to be in week 0.
You are perhaps looking for the ISO week date, but note that in this system the first day of the week is a Monday.
You can get the week number using that system with the datetime.date.isocalendar() method, or by formatting with %V:
>>> time.strftime("%V", time.localtime())
'38'
>>> from datetime import date
>>> date.today().isocalendar() # returns ISO year, week, and weekday
(2019, 38, 2)
>>> date.today().strftime("%V")
'38'
It's correct since you start counting from the first Sunday.
%U - week number of the current year, starting with the first Sunday as the first day of the first week
https://www.tutorialspoint.com/python/time_strftime.htm
It's correct. Since all days in a new year preceding the first Sunday are considered to be in week 0 (01/01 to 01/05), this week is the week 37.

Get number of days in a specific month that are in a date range

Haven't been able to find an answer to this problem. Basically what I'm trying to do is this:
Take a daterange, for example October 10th to November 25th. What is the best algorithm for determining how many of the days in the daterange are in October and how many are in November.
Something like this:
def daysInMonthFromDaterange(daterange, month):
# do stuff
return days
I know that this is pretty easy to implement, I'm just wondering if there's a very good or efficient algorithm.
Thanks
Borrowing the algorithm from this answer How do I divide a date range into months in Python?
, this might work. The inputs are in date format, but can be changed to date strings if preferred:
import datetime
begin = '2018-10-10'
end = '2018-11-25'
dt_start = datetime.datetime.strptime(begin, '%Y-%m-%d')
dt_end = datetime.datetime.strptime(end, '%Y-%m-%d')
one_day = datetime.timedelta(1)
start_dates = [dt_start]
end_dates = []
today = dt_start
while today <= dt_end:
#print(today)
tomorrow = today + one_day
if tomorrow.month != today.month:
start_dates.append(tomorrow)
end_dates.append(today)
today = tomorrow
end_dates.append(dt_end)
out_fmt = '%d %B %Y'
for start, end in zip(start_dates,end_dates):
diff = (end - start).days
print('{} to {}: {} days'.format(start.strftime(out_fmt), end.strftime(out_fmt), diff))
result:
10 October 2018 to 31 October 2018: 21 days
01 November 2018 to 25 November 2018: 24 days
The problem as stated may not have a unique answer. For example what should you get from daysInMonthFromDaterange('Feb 15 - Mar 15', 'February')? That will depend on the year!
But if you substitute actual days, I would suggest converting from dates to integer days, using the first of the month to the first of the next month as your definition of a month. This is now reduced to intersecting intervals of integers, which is much easier.
The assumption that the first of the month always happened deals with months of different lengths, variable length months, and even correctly handles the traditional placement of the switch from the Julian calendar to the Gregorian. See cal 1752 for that. (It will not handle that switch for all locations though. Should you be dealing with a library that does Romanian dates in 1919, you could have a problem...)
You can use the datetime module:
from datetime import datetime
start = datetime(2018,10,10)
end = datetime(2018,11,25)
print((end - start).days)
Something like this would work:
def daysInMonthFromDaterange(date1, date2, month):
return [x for x in range(date1.toordinal(), date2.toordinal()) if datetime.date.fromordinal(x).year == month.year and datetime.date.fromordinal(x).month == month.month]
print(len(days_in_month(date(2018,10,10), date(2018,11,25), date(2018,10,01))))
This just loops through all the days between date1 and date2, and returns it as part of a list if it matches the year and month of the third argument.

nth weekday calculation in Python - whats wrong with this code?

I'm trying to calculate the nth weekday for a given date. For example, I should be able to calculate the 3rd wednesday in the month for a given date.
I have written 2 versions of a function that is supposed to do that:
from datetime import datetime, timedelta
### version 1
def nth_weekday(the_date, nth_week, week_day):
temp = the_date.replace(day=1)
adj = (nth_week-1)*7 + temp.weekday()-week_day
return temp + timedelta(days=adj)
### version 2
def nth_weekday(the_date, nth_week, week_day):
temp = the_date.replace(day=1)
adj = temp.weekday()-week_day
temp += timedelta(days=adj)
temp += timedelta(weeks=nth_week)
return temp
Console output
# Calculate the 3rd Friday for the date 2011-08-09
x=nth_weekday(datetime(year=2011,month=8,day=9),3,4)
print 'output:',x.strftime('%d%b%y')
# output: 11Aug11 (Expected: '19Aug11')
The logic in both functions is obviously wrong, but I can't seem to locate the bug - can anyone spot what is wrong with the code - and how do I fix it to return the correct value?
Your problem is here:
adj = temp.weekday()-week_day
First of all, you are subtracting things the wrong way: you need to subtract the actual day from the desired one, not the other way around.
Second, you need to ensure that the result of the subtraction is not negative - it should be put in the range 0-6 using % 7.
The result:
adj = (week_day - temp.weekday()) % 7
In addition, in your second version, you need to add nth_week-1 weeks like you do in your first version.
Complete example:
def nth_weekday(the_date, nth_week, week_day):
temp = the_date.replace(day=1)
adj = (week_day - temp.weekday()) % 7
temp += timedelta(days=adj)
temp += timedelta(weeks=nth_week-1)
return temp
>>> nth_weekday(datetime(2011,8,9), 3, 4)
datetime.datetime(2011, 8, 19, 0, 0)
one-liner
You can find the nth weekday with a one liner that uses calendar from the standard library.
import calendar
calendar.Calendar(x).monthdatescalendar(year, month)[n][0]
where:
x : the integer representing your weekday (0 is Monday)
n : the 'nth' part of your question
year, month : the integers year and month
This will return a datetime.date object.
broken down
It can be broken down this way:
calendar.Calendar(x)
creates a calendar object with weekdays starting on your required weekday.
.monthdatescalendar(year, month)
returns all the calendar days of that month.
[n][0]
returns the 0 indexed value of the nth week (the first day of that week, which starts on the xth day).
why it works
The reason for starting the week on your required weekday is that by default 0 (Monday) will be used as the first day of the week and if the month starts on a Wednesday, calendar will consider the first week to start on the first occurrence of Monday (ie. week 2) and you'll be a week behind.
example
If you were to need the third Saturday of September 2013 (that month's US stock option expiry day), you would use the following:
calendar.Calendar(5).monthdatescalendar(2013,9)[3][0]
The problem with the one-liner with the most votes is it doesn't work.
It can however be used as a basis for refinement:
You see this is what you get:
c = calendar.Calendar(calendar.SUNDAY).monthdatescalendar(2018, 7)
for c2 in c:
print(c2[0])
2018-07-01
2018-07-08
2018-07-15
2018-07-22
2018-07-29
c = calendar.Calendar(calendar.SUNDAY).monthdatescalendar(2018, 8)
for c2 in c:
print(c2[0])
2018-07-29
2018-08-05
2018-08-12
2018-08-19
2018-08-26
If you think about it it's trying to organise the calendars into nested lists to print a weeks worth of dates at a time. So stragglers from other months come into play. By using a new list of valid days that fall in the month - this does the trick.
Answer with appended list
import calendar
import datetime
def get_nth_DOW_for_YY_MM(dow, yy, mm, nth) -> datetime.date:
#dow - Python Cal - 6 Sun 0 Mon ... 5 Sat
#nth is 1 based... -1. is ok for last.
i = -1 if nth == -1 or nth == 5 else nth -1
valid_days = []
for d in calendar.Calendar(dow).monthdatescalendar(yy, mm):
if d[0].month == mm:
valid_days.append(d[0])
return valid_days[i]
So here's how it could be called:
firstSundayInJuly2018 = get_nth_DOW_for_YY_MM(calendar.SUNDAY, 2018, 7, 1)
firstSundayInAugust2018 = get_nth_DOW_for_YY_MM(calendar.SUNDAY, 2018, 8, 1)
print(firstSundayInJuly2018)
print(firstSundayInAugust2018)
And here is the output:
2018-07-01
2018-08-05
get_nth_DOW_for_YY_MM() can be refactored using lambda expressions like so:
Answer with lambda expression refactoring
import calendar
import datetime
def get_nth_DOW_for_YY_MM(dow, yy, mm, nth) -> datetime.date:
#dow - Python Cal - 6 Sun 0 Mon ... 5 Sat
#nth is 1 based... -1. is ok for last.
i = -1 if nth == -1 or nth == 5 else nth -1
return list(filter(lambda x: x.month == mm, \
list(map(lambda x: x[0], \
calendar.Calendar(dow).monthdatescalendar(yy, mm) \
)) \
))[i]
The one-liner answer does not seem to work if the target day falls on the first of the month. For instance, if you want the 2nd Friday of every month, then the one-liner approach
calendar.Calendar(4).monthdatescalendar(year, month)[2][0]
for March 2013 will return March 15th 2013 when it should be March 8th 2013. Perhaps add in a check like
if date(year, month, 1).weekday() == x:
delivery_date.append(calendar.Calendar(x).monthdatescalendar(year, month)[n-1][0])
else:
delivery_date.append(calendar.Calendar(x).monthdatescalendar(year, month)[n][0])
Alternatively this will work for Python 2, returns the occurance of weekday in the said month, i.e if 16 June 2018 is the input, then returns the occurance of the day on 16th June 2018
You may substitute the month/year/date integers to anything you might want - right now it's getting the input / date from the system via datetime
Omit out print statements or use pass where they're not needed
import calendar
import datetime
import pprint
month_number = int(datetime.datetime.now().strftime('%m'))
year_number = int(datetime.datetime.now().strftime('%Y'))
date_number = int(datetime.datetime.now().strftime('%d'))
day_ofweek = str(datetime.datetime.now().strftime('%A'))
def weekday_occurance():
print "\nFinding current date here\n"
for week in xrange(5):
try:
calendar.monthcalendar(year_number, month_number)[week].index(date_number)
occurance = week + 1
print "Date %s of month %s and year %s is %s #%s in this month." % (date_number,month_number,year_number,day_ofweek,occurance)
return occurance
break
except ValueError as e:
print "The date specified is %s which is week %s" % (e,week)
myocc = weekday_occurance()
print myocc
A little tweak would make the one-liner work correctly:
import calendar
calendar.Calendar((weekday+1)%7).monthdatescalendar(year, month)[n_th][-1]
Here n_th should be interpreted as c-style, e.g. 0 is the first index.
Example: to find 1st Sunday in July 2018 one could type:
>>> calendar.Calendar(0).monthdatescalendar(2018, 7)[0][-1]
datetime.date(2018, 7, 1)
People here seem to like one-liner, I will propose below.
import calendar
[cal[0] for cal in calendar.Calendar(x).monthdatescalendar(year, month) if cal[0].month == month][n]
The relativedelta module that's an extension from the Python dateutil package (pip install python-dateutil) does exactly what you want:
from dateutil import relativedelta
import datetime
def nth_weekday(the_date, nth_week, week_day):
return the_date.replace(day=1) + relativedelta.relativedelta(
weekday=week_day(nth_week)
)
print(nth_weekday(datetime.date.today(), 3, relativedelta.FR))
The key part here evaluates to weekday=relativedelta.FR(3): the third Friday of the month. Here are the relevant part of the docs for the weekday parameter,
weekday:
One of the weekday instances (MO, TU, etc) available in the
relativedelta module. These instances may receive a parameter N,
specifying the Nth weekday, which could be positive or negative
(like MO(+1) or MO(-2)).

Pythonic difference between two dates in years?

Is there a more efficient way of doing this below? I want to have the difference in years between two dates as a single scalar. Any suggestions are welcome.
from datetime import datetime
start_date = datetime(2010,4,28,12,33)
end_date = datetime(2010,5,5,23,14)
difference = end_date - start_date
difference_in_years = (difference.days + difference.seconds/86400)/365.2425
If you want precise results, I recommend using the dateutil library.
from dateutil.relativedelta import relativedelta
difference_in_years = relativedelta(end_date, start_date).years
This is for complete years (e.g. a person's age). If you want fractional years, then add months, days, hours, ... up to the desired precision.
I use one of these to calculate person's age:
import datetime
dob = datetime.date(1980, 10, 10)
def age():
today = datetime.date.today()
years = today.year - dob.year
if today.month < dob.month or (today.month == dob.month and today.day < dob.day):
years -= 1
return years
def age2():
today = datetime.date.today()
this_year_birthday = datetime.date(today.year, dob.month, dob.day)
if this_year_birthday < today:
years = today.year - dob.year
else:
years = today.year - dob.year - 1
return years
Just do this:
from dateutil.relativedelta import relativedelta
myBirthday = datetime.datetime(1983,5,20,0,0,0,0)
now = datetime.datetime.now()
difference = relativedelta(now, myBirthday)
print("My years: "+str(difference.years))
More efficient? No, but more correct, probably. But it depends on how correct you want to be. Dates are not trivial things.
Years do not have a constant length. Do you want the difference in leap years or normal years? :-) As you calculate you are always going to get a slightly incorrect answer. And how long is a day in years? You say 1/365.2425. Well, yeah, averaged over a thousand years, yeah. But otherwise not.
So the question doesn't really make much sense.
To be correct you have to do this:
from datetime import datetime
from calendar import isleap
start_date = datetime(2005,4,28,12,33)
end_date = datetime(2010,5,5,23,14)
diffyears = end_date.year - start_date.year
difference = end_date - start_date.replace(end_date.year)
days_in_year = isleap(end_date.year) and 366 or 365
difference_in_years = diffyears + (difference.days + difference.seconds/86400.0)/days_in_year
In this case that's a difference of 0.0012322917425568528 years, or 0.662 days, considering that this is not a leap year.
(and then we are ignoring microseconds. Heh.)
To make sense of leap years, you are almost forced to break this into two parts: an integral number of years, and a fractional part. Both need to deal with leap years, but in different ways - the integral needs to deal with a starting date of February 29, and the fractional must deal with the differing number of days in a year. You want the fractional part to increment in equal amounts until it equals 1.0 at the next anniversary date, so it should be based on the number of days in the year after the end date.
Do you want your date range to include 1900 or 2100? Things get a little easier if you don't.
Edit: It has taken me a long time to reason this through. The basic problem is that calendar years are not a constant size, but you're coercing them to be constant by setting them to 1.0. Any solution you come up with is going to have anomalies because of this, and you're going to have to choose which anomalies you can live with. John Machin was right.
What's the difference between 2008-02-28 and 2009-02-28? Most people would agree that it should be exactly 1.0 years. How about the difference between 2008-03-01 and 2009-03-01? Again, most people would agree that it should be exactly 1.0 years. If you choose to represent a date as a year plus a fraction of a year based on the day, it is impossible to make both of these statements true. This is the case for your original code which assumed a day was 1/365.2425 of a year, or indeed for any code which assumes a constant fraction of a year per day, even if the size of a day accounts for the years which are leap years.
My assertion that you needed to break this down into integral years and fractional years was an attempt to get around this problem. If you treat each of the previous conditions as an integral year, all you have to do is decide on which fraction to assign to any number of days left over. The problem with this scheme is that you still can't make sense of (date2-date1)+date3, because the fraction can't be resolved back to a day with any consistency.
Thus I am proposing yet another encoding, based on each year containing 366 days whether it is a leap year or not. The anomalies will firstly be that there can't be a date which is exactly a year (or 2 or 3) from Feb. 29 - "Sorry Johnny, you don't get a birthday this year, there's no Feb. 29" isn't always acceptable. Second is that if you try to coerce such a number back to a date, you'll have to account for non-leap years and check for the special case of Feb. 29 and convert it, probably to Mar. 1.
from datetime import datetime
from datetime import timedelta
from calendar import isleap
size_of_day = 1. / 366.
size_of_second = size_of_day / (24. * 60. * 60.)
def date_as_float(dt):
days_from_jan1 = dt - datetime(dt.year, 1, 1)
if not isleap(dt.year) and days_from_jan1.days >= 31+28:
days_from_jan1 += timedelta(1)
return dt.year + days_from_jan1.days * size_of_day + days_from_jan1.seconds * size_of_second
start_date = datetime(2010,4,28,12,33)
end_date = datetime(2010,5,5,23,14)
difference_in_years = date_as_float(end_time) - date_as_float(start_time)
I'm not suggesting that this is the solution, because I don't think a perfect solution is possible. But it has some desirable properties:
The difference between any dates with the same month and day and time will be an exact number of years.
Adding a difference to another date will result in a value that can be converted back into a useful date.
I think what you're looking for is:
difference_in_years = difference.dt.days / 365.25
Here's a spin off of what Kostyantyn posted in his "age2" function. It's slightly shorter/cleaner and uses the traditional/colloquial meaning of an "age" or difference in years as well:
def ageInYears( d ):
today = datetime.date.today()
currentYrAnniversary = datetime.date( today.year, d.month, d.day )
return (today.year - d.year) - (1 if today < currentYrAnniversary else 0)
Since we're coming to the end of 2018...
from dateutil import parser
from dateutil.relativedelta import relativedelta
rip = [
["Tim Bergling\t\t", " 8 Sep 1989", "20 Apr 2018"], # Avicii Swedish musician
["Stephen Hillenburg\t", "21 Aug 1961", "26 Nov 2018"], # Creator of Spongebob
["Stephen Hawking\t\t", " 8 Jan 1942", "14 Mar 2018"], # Theoretical physicist
["Stan Lee\t\t", "28 Dec 1922", "12 Nov 2018"], # American comic book writer
["Stefán Karl Stefánsson\t", "10 Jul 1975", "21 Aug 2018"] # Robbie Rotten from LazyTown
]
for name,born,died in rip:
print("%s %s\t %s\t died at %i"%(name,born,died,relativedelta(parser.parse(died),parser.parse(born)).years))
output
Tim Bergling 8 Sep 1989 20 Apr 2018 died at 28
Stephen Hillenburg 21 Aug 1961 26 Nov 2018 died at 57
Stephen Hawking 8 Jan 1942 14 Mar 2018 died at 76
Stan Lee 28 Dec 1922 12 Nov 2018 died at 95
Stefán Karl Stefánsson 10 Jul 1975 21 Aug 2018 died at 43
If you mean efficient in terms of code space then no, that's about the most efficient way to do that.
Here's what I came up with, without using an external dependency:
def year_diff(d1, d2):
"""Returns the number of years between the dates as a positive integer."""
later = max(d1, d2)
earlier = min(d1, d2)
result = later.year - earlier.year
if later.month < earlier.month or (later.month == earlier.month and later.day < earlier.day):
result -= 1
return result
More robust function - calculates difference in years (age) and days:
def get_diff_in_years_and_days(from_date, to_date):
try:
from_in_this_year = date(to_date.year, from_date.month, from_date.day)
except:
from_in_this_year = date(to_date.year, from_date.month, from_date.day-1) # today is feb in leap year
if from_in_this_year <= to_date:
years = to_date.year - from_date.year
days = (to_date - from_in_this_year).days
else:
years = to_date.year - from_date.year - 1
try:
from_in_prev_year = date(to_date.year-1, from_date.month, from_date.day)
except:
from_in_prev_year = date(to_date.year-1, from_date.month, from_date.day-1) # today is feb in leap year
days = (to_date - from_in_prev_year).days
assert days>=0 and days<=365, days
assert years>=0, years
return years, days
some unit-tests:
self.assertEqual((0, 0), get_diff_in_years_and_days(date(2018,1, 1), date(2018,1, 1)))
self.assertEqual((1, 0), get_diff_in_years_and_days(date(2017,1, 1), date(2018,1, 1)))
self.assertEqual((1, 1), get_diff_in_years_and_days(date(2017,1, 1), date(2018,1, 2)))
self.assertEqual((2, 0), get_diff_in_years_and_days(date(2016,2,29), date(2018,2,28)))
self.assertEqual((2, 1), get_diff_in_years_and_days(date(2014,2,28), date(2016,2,29)))
self.assertEqual((1,364), get_diff_in_years_and_days(date(2014,2,28), date(2016, 2,27)))
self.assertEqual((3,30) , get_diff_in_years_and_days(date(2015,10,1), date(2018,10,31)))
self.assertEqual((10,30), get_diff_in_years_and_days(date(2010,10,1), date(2020,10,31)))
self.assertEqual((3,31) , get_diff_in_years_and_days(date(2015,10,1), date(2018,11, 1)))
self.assertEqual((2,364), get_diff_in_years_and_days(date(2015,10,1), date(2018, 9,30)))
Before install library :
choco upgrade Python -y
python pip install python-dateutil
In One line in Python in Cmder (windows) :
python -c "import datetime; from dateutil.relativedelta import relativedelta; myBirthday = datetime.datetime(2019,2,6,11,0,0,0); now = datetime.datetime.utcnow(); diff = relativedelta(now, myBirthday); print ("'My'+'" "'+'year'+'" "'+':'+'" "'+'%d''" "''and''" "''%d''" "''microseconds'" % (diff.years, diff.microseconds))"
In Batch escape percent with %% :
python -c "import datetime; from dateutil.relativedelta import relativedelta; myBirthday = datetime.datetime(2019,2,6,11,0,0,0); now = datetime.datetime.utcnow(); diff = relativedelta(now, myBirthday); print ("'My'+'" "'+'year'+'" "'+':'+'" "'+'%%d''" "''and''" "''%%d''" "''microseconds'" %% (diff.years, diff.microseconds))"
An update to BuvinJ solution which was an update to the Kostyantyn solution, age2().
Those functions fail if the date of birth is on leap day and the current year is not a leap year. The datetime library will throw an exception when trying to create 'currentYrAnniversary'.
Instead try,
from datetime import date
def ageInYears( d ):
today = datetime.date.today()
notQuiteYourBirthday = (today.month, today.day) < (born.month, born.day)
return (today.year - d.year) - notQuiteYourBirthday
If you have the DOB as a string already you can do this:
from datetime import datetime as dt
def get_age(dob_str):
now_str = dt.strftime(dt.utcnow(), '%Y-%m-%d')
return int(now_str[:4]) - int(dob_str[:4]) - int(dob_str[5:] > now_str[5:])
Or if you want to write some unit tests set now_str as a named parameter:
from datetime import datetime as dt
def get_age(dob_str, now_str=dt.strftime(dt.utcnow(), '%Y-%m-%d')):
return int(now_str[:4]) - int(dob_str[:4]) - int(dob_str[5:] > now_str[5:])
The simplest solution
from datetime import datetime
my_birthday = datetime(2000, 1, 1, 0, 0, 0, 0 )
now = datetime.now()
age = now.year - my_birthday.year
print(age)

Categories