Home > Enterprise >  Python3 - datetime function -- clarification on .days meaning
Python3 - datetime function -- clarification on .days meaning

Time:10-05

I am wanting to take user input of date1 and date2 and calculate the difference to determine how many weeks are in between. My entire program is below. The example dates I'm using are:

date1 = 2023-03-15

date2 = 2022-11-09

Output is Number of weeks: 18 -- which is correct.

My 1st question that I need help in clarifying is why do I need the .days after the days = abs(date2-date1).days? I have searched for many hours via Google, stackoverflow, Youtube and Python docs https://docs.python.org/3.9/library/datetime.html?highlight=datetime#module-datetime. I'm pretty new to Python and reading the docs sometimes trips me up, so please forgive if it's in there -- I've struggled reading through some of it. Why is the .days needed? I know that if I remove .days, the output is: Number of weeks: 18 days, 0:00:00. Where is the documentation on needing the .days listed in the datetime module docs??? Can someone help me understand this please?

My 2nd question is why do I get Number of weeks: 0 when I change .days to .seconds? (this is when I was testing things and comment out the weeks = days//7 and print out days) The one part in the docs that I think addresses this the following: https://docs.python.org/3.9/library/datetime.html?highlight=datetime#module-datetime:~:text=the given year.-,Supported operations:,!=. The latter cases return False or True, respectively.,-In Boolean contexts.... and if this is correct, am I reading it correctly that if the difference in dates are to be determined, only "days" are returned, and thus no seconds or microseconds?

Thank you for your help! Code below:

#Find the number of weeks between two given dates

from datetime import datetime

#User input for 1st date in YYYY-MM-DD format
date1 = input("Enter 1st date in YYYY-MM-DD format: ")
date1 = datetime.strptime(date1, "%Y-%m-%d")

#User input for 2nd date in YYYY-MM-DD format
date2 = input("Enter 2nd date in YYYY-MM-DD format: ")
date2 = datetime.strptime(date2, "%Y-%m-%d")

#Calculate the weeks between the 2 given dates
days = abs(date2-date1).days
weeks = days//7

print("Number of weeks: ", weeks)

Output-correct answer with .days included:

Enter 1st date in YYYY-MM-DD format: 2023-03-15
Enter 2nd date in YYYY-MM-DD format: 2022-11-09
Number of weeks:  18

Output-with no .days added:

Enter 1st date in YYYY-MM-DD format: 2023-03-15
Enter 2nd date in YYYY-MM-DD format: 2022-11-09
Number of weeks:  18 days, 0:00:00

Output-(regarding 2nd question with the .seconds put in place of .days:

Enter 1st date in YYYY-MM-DD format: 2023-03-15
Enter 2nd date in YYYY-MM-DD format: 2022-11-09
Number of weeks:  0

CodePudding user response:

Subtracting two datetime.datetime objects returns a datetime.timedelta object:

>>> date1 = datetime.strptime('2023-03-15', "%Y-%m-%d")
>>> date2 = datetime.strptime('2022-11-09', "%Y-%m-%d")
>>> date2-date1
datetime.timedelta(days=-126)
>>> 

From the docs:

Only days, seconds and microseconds are stored internally. Arguments are converted to those units:

A millisecond is converted to 1000 microseconds.

A minute is converted to 60 seconds.

An hour is converted to 3600 seconds.

A week is converted to 7 days.

Here is some example usage of datetime.timedelta objects. So for your second question, I believe that you're right; for the difference between two days, there are no .seconds, as it is strictly a difference of days. For .seconds to be nonzero, you'd have to have some component of the difference that is larger than a 1,000,000 microseconds but smaller than 86,400 seconds, I suppose.

CodePudding user response:

TL;DR: The answer to both of your questions is "because that is a property of the datetime.timedelta class."

More fully, the date1 and date2 objects you create in your code are both instances of the datetime.datetime class. The - operation between them makes a timedelta object.

  1. Why is the .days needed to avoid printing ", 0:00:00"?

By default all the date information in the timedelta object you created with the operation abs(date2-date1) is printed (including seconds and microseconds, even after modifying it with the //7 operation). When you use the . operator, you access the days attribute of the timedelta object, and only that attribute's value is used.

  1. Why do I get "Number of weeks: 0" when I change .days to .seconds?

The value of the seconds attribute of the timedelta object you created with the operation abs(date2-date1) is integer 0.

See below:

>>> from datetime import datetime

>>> date1 = "2023-03-15"
>>> date1, type(date1)
('2023-03-15', <class 'str'>)

>>> date1 = datetime.strptime(date1, "%Y-%m-%d")
>>> date1, type(date1)
(datetime.datetime(2023, 3, 15, 0, 0), <class 'datetime.datetime'>)

>>> date2 = "2022-11-09"
>>> date2, type(date2)
('2022-11-09', <class 'str'>)

>>> date2 = datetime.strptime(date2, "%Y-%m-%d")
>>> date2, type(date2)
(datetime.datetime(2022, 11, 9, 0, 0), <class 'datetime.datetime'>)

>>> abs(date2-date1), type(abs(date2-date1))
(datetime.timedelta(days=126), <class 'datetime.timedelta'>)

>>> abs(date2-date1).days, type(abs(date2-date1).days)
(126, <class 'int'>)

>>> abs(date2-date1).seconds, type(abs(date2-date1).seconds)
(0, <class 'int'>)

See also: this discussion.

CodePudding user response:

To be precise you calculate difference in 7 days intervals, but the week is actualy a time period which starts on Monday (or Sunday) and ends on Sunday (or Monday). So the difference between 2022-10-01 (Sat) and 2022-10-04 (Tue) in weeks of year is 1, but in days is 3 (0 7days intervals in your case).

So if you need to find the distance between two dates in weeks of year you have to take account of the weekdays:

from datetime import date

d1 = date(2022,10,18)
d2 = date(2022,10,5)
w1 = d1.weekday()
w2 = d2.weekday()

# dfference in weeks of year = 2
((d1-d2).days - (w1-w2))/7  # 2.0

# difference in days = 13
d1-d2  # datetime.timedelta(days=13)
  • Related