How to subtract a date object from another in Python - python

I want to find how many days there are between two days. The next step is to find out how many hours there are between two days, but that's for later. I created a date object with today's date, and another date object with user inputs, then subtract the smaller date from the larger date. I think this is where I'm going wrong because it does not make sense to subtract a date from another date when both are naive, but it would make sense to subtract a datetime from another datetime (aware)?
I've verified the types of the objects using print(type(var)). Both created objects are of type date, and the result of subtracting is a timedelta object, as expected. Subtracting the date objects gives me the wrong number of days (400 something) when it should be 350 in my case.
from datetime import date, timedelta, datetime
days = list(range(1, 32))
months = list(range(1, 13))
today = date.today()
def inputInteger(message):
while True:
try:
userInput = int(input(message))
except ValueError:
print("Please enter an integer.")
continue
else:
return userInput
break
def inputMonth(message):
while True:
message = inputInteger(message)
if message in months:
return message
break
else:
print("Please pick a value from 1-12")
def inputDay(message):
while True:
message = inputInteger(message)
if int(message) in days:
return message
break
else:
print("Please pick a value from 1-31")
year = int(inputInteger('Enter a year'))
month = int(inputMonth('Enter a month (1-12)'))
day = int(inputDay('Enter a day (1-31)'))
# 2. add exception handling: leap years, leap seconds?, etc.
significantDate = date(year, month, day)
print("significant date:", significantDate, "of type", type(significantDate))
print("today:", today, "of type", type(today))
# 2. Tell me how many days are left until a certain date
if today > significantDate:
delta = today - significantDate
print("Days left:", delta.days)
else:
print("entered less than")
delta = significantDate - today
print("Days left:", delta.days)
```

from datetime import datetime
year = int(inputInteger('Enter a year'))
month = int(inputMonth('Enter a month (1-12)'))
day = int(inputDay('Enter a day (1-31)'))
significantDate =datetime.strptime(str(year) +str(month) + str(day), '%Y%m%d')
today = datetime.now()
print(today)
dt = today - significantDate
print(dt.days)

Related

Check if date is between two dates without year included

I have a datetime date in the format yyyy-mm-dd and I want to check if the date entered falls between for example May 15th and May 25th without including any year value.
tripDate_str = str(input("Please enter the trip start date in the following format: YYYY-MM-DD "))
import datetime
tripDate = datetime.datetime.strptime(tripDate_str, "%Y-%m-%d")
Well I guess the simplest approach is to use the month and day date class attributes
import datetime
tripDate = datetime.datetime.strptime('2022-05-15', "%Y-%m-%d")
start = datetime.datetime.strptime('2022-05-10', "%Y-%m-%d")
end = datetime.datetime.strptime('2022-05-20', "%Y-%m-%d")
if tripDate.month >= start.month and tripDate.month <= end.month and tripDate.day >= start.day and tripDate.day <= end.day:
print('Date in range')
else:
print('Date not in range')
There are many options to get the day of the year from a date. Use a search engine with keywords python day of year to find out which or just look here at stackoverflow ("Convert Year/Month/Day to Day of Year in Python"). The code below is using for this purpose dateObject.timetuple().tm_yday:
tripDate_str = str(input("Please enter the trip start date in the following format: YYYY-MM-DD "))
# tripDate_str = "2022-05-18"
## Finding day of year
from datetime import date
tripDate = date(*map(int, tripDate_str.split('-')))
tripDate_dayOfYear = tripDate.timetuple().tm_yday
print("Day of year: ", tripDate_dayOfYear, type(tripDate_dayOfYear))
dateRangeBeg_dayOfYear = date(tripDate.year, 5, 15).timetuple().tm_yday
dateRangeEnd_dayOfYear = date(tripDate.year, 5, 25).timetuple().tm_yday
if dateRangeBeg_dayOfYear <= tripDate_dayOfYear <= dateRangeEnd_dayOfYear:
print("tripDate falls into range", dateRangeBeg_dayOfYear, dateRangeEnd_dayOfYear)
else:
print("tripDate is outside range", dateRangeBeg_dayOfYear, dateRangeEnd_dayOfYear)
To avoid a problem with leap years tripDate.year is used in setting the values of dateRangeBeg_dayOfYear and dateRangeEnd_dayOfYear.

Calculate the N th day of the previous year

I have a date in the format "YYYY-MM-DD", for example "2022-03-09". It is the 68th day of the year 2022. Is there a way to get the 68th day of 2021? More generally, if I have a date in "YYYY-MM-DD" format, which is the N th day of the year, is there a quick way to calculate the N th day of the previous year?
You could do:
from datetime import datetime, timedelta
date_string = '2020-03-09'
# Parse the string to a datetime.date object
date = datetime.strptime(date_string, '%Y-%m-%d')
# Get the number N of the day in the year
N = date.timetuple().tm_yday
# Take 1st of january of last year and add N-1 days
N_last_year = (
date.replace(year=date.year-1, month=1, day=1) +
timedelta(days=N-1)
)
print(N_last_year.date())
Or, another funny solution based on leap years. It is based on the fact that the Nth day of last year is the same as this year's, except if the date is after 29th february and there is a leap year somewhere.
from datetime import datetime, timedelta
def leap(year: int) -> bool:
# Returns True if year is a leap year, False otherwise
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
date_string = '2020-03-09'
# Parse the string to a datetime.date object
date = datetime.strptime(date_string, '%Y-%m-%d')
# Get the number N of the day in the year
N = date.timetuple().tm_yday
date_last_year = date.replace(year=date.year-1)
# Do the cool thing
if date.month >= 3:
if leap(date.year):
date_last_year += timedelta(days=1)
elif leap(date.year-1):
date_last_year += timedelta(days=-1)
print(date_last_year.date())
The datetime objects will you with that (https://docs.python.org/3/library/datetime.html).
Indeed, you can compute the time lap between your date and the beginning of the year. Then you can add this difference to the beginning of the next year.
import datetime
date_string = "2022-03-09"
date_object = datetime.datetime.strptime(date_string, "%Y-%m-%d").date()
beginning_of_year = datetime.date(date_object.year, 1, 1)
time_difference = date_object - beginning_of_year
beginning_of_last_year = datetime.date(date_object.year - 1, 1, 1)
same_day_last_year = beginning_of_last_year + time_difference
print(same_day_last_year)
However, the result is disappointing, since it is in fact the same date...
I think you can do something like
from datetime import timedelta, date
year = timedelta(days=365)
today = date.fromisoformat("2022-03-09")
print(today - year)

Why is my program outputting the wrong number of days?

So I am writing a program to work out the number of days you have been alive after imputting your birthday. There is a problem as i am getting the wrong number of days but can figure out why. i inputted my birthday as 04/04/19 and i got 730625 days which is clearly wrong.
import datetime #imports module
year = int(input("What year were you born in"))
month = int(input("What month where you born in (number)"))
date = int(input("What date is your birthday? "))
birthdate = datetime.date(date, month, year) #converts to dd/mm/yy
today = datetime.date.today() #todays date
daysAlive = (today - birthdate).days #calculates how many days since birth
print("You have been alive for {} days.".format(daysAlive)) #outputs result
I initially got the same error as you but then I checked my code and managed to fix my mistake.
So your DOB is 04/04/19, when you input that into datetime.date() and it looks at the value for year which is 19, it will treat that as 0019. As in 19 AD, not 2019. You should make sure that you input the full year.
Also like SimonN said, the parameters for datetime.date() are year, month, day, not the other way around.
You have the parameters the wrong way round in datetime.date they should be (year,month,day)
datetime takes arguments as (year, month, date). Note that you cannot enter year like 09 for 2009. Datetime will count it as 0009-MM-DD. You have to enter complete year in the input as 2009
...
birthdate = datetime.date(year, month, date)
...
So, with your input, the output for me is (It may differ with your timezone):
You have been alive for 170 days.
class datetime.date(year, month, day)
should be in the format yy/mm/dd.
Try this code for Python 3.6 or higher,
because of f-stings:
import datetime
year = int(input("What year were you born in: "))
month = int(input("What month were you born in (number): "))
day = int(input("What day were you born in: "))
birth_date = datetime.date(year, month, day) # converts to yy/mm/dd
today = datetime.date.today() # todays date
days_alive = (today - birth_date).days # calculates how many days since birth
print(f"You are {days_alive} days old.") # outputs result
Check the answer using other sources.

Convert int to date

I'm trying to convert yyyy/mm/dd to dd/mm/yyyy, from integer inputs.
When i've changed the pattern inside the parethesis from datetime.date(year, month, day), to datetime.date(day, month, year), it returns an Value error.
def acc_expiration():
year = int(input('YEAR: '))
month = int(input('MONTH: '))
day = int(input('DAY: '))
exp_date = datetime.date(day, month, year)
return exp_date
ValueError: day is out of range for month
From the documentation:
class datetime.date(year, month, day)
This means you need to put the arguments in the right position, doesn't matter how you want to print it later.
This should work:
def acc_expiration():
year = int(input('YEAR: '))
month = int(input('MONTH: '))
day = int(input('DAY: '))
exp_date = datetime.date(year, month, day)
return exp_date
Now let's print it formatted in dd/mm/yyyy:
d = acc_expiration()
f = d.strftime('%d/%m/%Y')
print(f) # prints it formatted dd/mm/yyyy
Your value error is because you are giving a year integer (integer bigger than 31) to the day argument, and for the year you are giving the day integer.
You are confusing the object from its presentation.
Look at the Python docs for Datetime (here)
The correct sequence for datetime.date is class datetime.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])
Once you have a datetime object, you can format the output of it in a variety of ways to suit your needs.
Does that help?

Python Datetime problem: Is There a better solution

I found the correct solution to the following problem which uses python 3 datetime objects. However, my solution seems really messy and I was wondering if I could get some help to clean it up:
Question:
Complete the which_date() function below which returns the day that follows a specified time period after an initial date. Time periods can be specified in two different ways: as a number of days like "1 day" or "30 days", or as a number of weeks like "2 weeks" or "12 weeks".
def which_date(start_date,time):
"""
This function takes as input a string depicting a date in YYYY/mm/dd
format and a string stating a time period in the form of "X day(s)" or
"Y week(s)". Output should be a string in form YYYY/mm/dd with the date
that is X days or Y weeks after the initial date.
"""
# Every thing after this comment and before 'return end_date' is my
#code to solve this probmem
start_date_split = start_date.split('/')
start_date_split = list(map(int, start_date_split))
year, month, day = start_date_split[0], start_date_split[1],
start_date_split[2]
start_date_date_obj = datetime.date(year, month, day)
time_split = time.split(' ')
time_amount = int(time_split[0])
days_or_weeks = time_split[1]
time_to_add = datetime.timedelta(0)
if 'day' in days_or_weeks:
time_to_add = datetime.timedelta(days = time_amount)
else:
time_to_add = datetime.timedelta(weeks = time_amount)
end_date_date_obj = start_date_date_obj + time_to_add
end_date = end_date_date_obj.strftime('%Y/%m/%d')
return end_date
The following is the verification test:
def test():
assert which_date('2016/02/10','35 days') == '2016/03/16'
assert which_date('2016/12/21','3 weeks') == '2017/01/11'
assert which_date('2015/01/17','1 week') == '2015/01/24'
print("All tests completed.")
Did some list destructuring to cut down on some lines of code. Also removed the creation of some new variables and just used the values directly:
import datetime
def which_date(start_date,time):
"""
This function takes as input a string depicting a date in YYYY/mm/dd
format and a string stating a time period in the form of "X day(s)" or
"Y week(s)". Output should be a string in form YYYY/mm/dd with the date
that is X days or Y weeks after the initial date.
"""
# Every thing after this comment and before 'return end_date' is my
# code to solve this problem
year, month, day = [int(each) for each in start_date.split('/')]
start_date_date_obj = datetime.date(year, month, day)
time_amount, days_or_weeks = [int(value) if index==0 else value for index, value in enumerate(time.split(' '))]
time_to_add = datetime.timedelta(days = time_amount) if days_or_weeks=='days' else datetime.timedelta(weeks = time_amount)
return (start_date_date_obj + time_to_add).strftime('%Y/%m/%d')
def test():
assert which_date('2016/02/10','35 days') == '2016/03/16'
assert which_date('2016/12/21','3 weeks') == '2017/01/11'
assert which_date('2015/01/17','1 week') == '2015/01/24'
print("All tests completed.")
test()
You can use regular expressions in order to have a 'cleaner' function:
import re
import datetime
def which_date(start_date, time):
# Split your date into a list by using non-decimal characters as separators
year, month, day = re.split(r'\D', start_date)
start_date_date_obj = datetime.date(int(year), int(month), int(day))
# Create group captures in order to get the quantity of day(s)/week(s)
# and pass those as generic arguments to timedelta
time_match = re.search(r'(\d+) (day|week)[s]?', time)
args = {time_match.group(2) + 's': int(time_match.group(1))}
time_to_add = datetime.timedelta(**args)
end_date_date_obj = start_date_date_obj + time_to_add
end_date = end_date_date_obj.strftime('%Y/%m/%d')
return end_date
Here's a more simple version of a previous answer. I'm a beginner so I can't understand all of the advanced code here.
import datetime
def which_date(start_date,time):
"""
This function takes as input a string depicting a date in YYYY/mm/dd
format and a string stating a time period in the form of "X day(s)" or
"Y week(s)". Output should be a string in form YYYY/mm/dd with the date
that is X days or Y weeks after the initial date.
"""
year, month, day = [int(each) for each in start_date.split('/')]
start_date_date_obj = datetime.date(year, month, day)
add = 1
string = time.split()
if string[1] == "days" or string[1] == "day":
add = int(string[0])
else:
add = (int(string[0]))*7
time_to_add = datetime.timedelta(days = add)
end_date = (start_date_date_obj + time_to_add).strftime('%Y/%m/%d')
return end_date

Categories