How to add/subract operation between two different times using timedelta? - python

So i'm trying know in what time of day the man will end running. When in last line of code, trying to use an operator addition this error is popping out. What i'm doing wrong?
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'
import datetime
# first run, 1 mile
pace_minutes1 = 8
pace_seconds1 = 15
distance = 1 #1 mile
b = ((pace_minutes1 * 60) + pace_seconds1) * distance
print(b)
# second run, 3 mile
pace_minutes2 = 7
pace_seconds2 = 12
distance = 3 # 3 miles
a = ((pace_minutes2 * 60) + pace_seconds2) * distance
print(a)
# third run, 1 mile run
pace_minutes3 = 8
pace_seconds3 = 15
distance = 1 # 1 mile
c = ((pace_minutes3 * 60) + pace_seconds3) * distance
print(c)
x = (a + b + c)
print(x, "seconds")
time = datetime.timedelta(seconds=x) # converse value "x" seconds to time (h,m,s)
print("All running time will gonna take",time,"seconds") # total time spent running
start_time = datetime.time(6,52,0) # time from where he started running
print("The running started in",start_time)
end_time = (start_time + time) # time when he ended running
print(end_time)

You can only add the timedelta to a datetime.datetime object, not a datetime.time object (probably in order to avoid overflows).
So simple fix, use start_time = datetime.datetime(2021, 04, 21, 6,52,0)

Please find below answer .check if it what you desired.May be you can check stack overflow answer
import datetime
# first run, 1 mile
pace_minutes1 = 8
pace_seconds1 = 15
distance = 1 #1 mile
b = ((pace_minutes1 * 60) + pace_seconds1) * distance
print(b)
# second run, 3 mile
pace_minutes2 = 7
pace_seconds2 = 12
distance = 3 # 3 miles
a = ((pace_minutes2 * 60) + pace_seconds2) * distance
print(a)
# third run, 1 mile run
pace_minutes3 = 8
pace_seconds3 = 15
distance = 1 # 1 mile
c = ((pace_minutes3 * 60) + pace_seconds3) * distance
print(c)
x = (a + b + c)
print(x, "seconds")
time = datetime.timedelta(seconds=x) # converse value "x" seconds to time (h,m,s)
print("All running time will gonna take",time,"seconds") # total time spent running
start_time = datetime.time(6,52,0) # time from where he started running
# print(type(start_time))
# print(type(time))
print("The running started in",start_time)
end_time = (dt.datetime.combine(dt.date(1,1,1),start_time) + time).time()
print(end_time)

Related

Python print() function not recalculating variables in a while loop

I am attempting to write a program that will calculate the difference in a given time and the actual time then display that delta in a while loop. I have been able to get most of this working, the only issue I have found so far is the time variables in the print statement do not update as the loop runs.
import datetime
import time
from os import system
from sys import platform
clear_screen = lambda: system("cls" if platform == "win32" else "clear")
# print("What is the time and date of your event?")
# year = int(input("Year: "))
# month = int(input("Month: "))
# day = int(input("Day: "))
# hour = int(input("Hour: "))
# minute = int(input("Minute: "))
i = 0
year = 2023
month = 1
day = 27
hour = 12
minute = 0
second = 00
today = datetime.datetime.now()
date_entry = datetime.datetime(year, month, day, hour, minute, second)
print(f"The current date & time: {today}")
print(f"The big day is: {date_entry}")
print()
print()
print(f"Tiff's Big day is going to be here soon:")
print()
event_count = date_entry - today
event_hour = event_count.total_seconds() / 3600
event_min = ((event_hour % 1) * (60 / 100)) * 100
event_sec = ((event_min % 1) * (60 / 100)) * 100
def countdown():
print(f"{event_hour:.0f} Hours, {event_min:.0f} Minutes, {event_sec:.0f} seconds until big mode!!!!!")
while i < 50:
i += 1
countdown()
time.sleep(2)
# clear_screen()`
I have a feeling that the time variables in the print statement are not recalculating... I have tried restructuring the program by moving the variables into the countdown() function. That had the same result.
I am expecting the script to output hours, minutes and seconds until a defined time. This part works great. Then pause for 2 seconds (this works) then print the statement again after it recalculates the time delta. This is were it fails, prints the exact same time as in the first print statement.
You might also notice the clear_screen(). This kinda works, it will clear all of the output. I am looking to make it clear the last line printed in the loop (ie: 40 Hours, 12 Minutes, 56 seconds until big mode!!!!!) This is something I haven't looked at much yet. If you have any suggestions...
Thanks in advance for any suggestions.
Output:
The current date & time: 2023-01-25 19:48:04.383425
The big day is: 2023-01-27 12:00:00
Tiff's Big day is going to be here soon:
40 Hours, 12 Minutes, 56 seconds until big mode!!!!!
40 Hours, 12 Minutes, 56 seconds until big mode!!!!!
40 Hours, 12 Minutes, 56 seconds until big mode!!!!!
40 Hours, 12 Minutes, 56 seconds until big mode!!!!!
40 Hours, 12 Minutes, 56 seconds until big mode!!!!!
Be careful with calling time functions, the time is assigned to a variable only the first time, here is an example in the REPL:
>>> import time
>>> time.time()
1674700748.035392
>>> time.time()
1674700749.2911549
>>> time.time()
1674700750.440412
>>> time.time()
1674700751.571879
>>> x = time.time()
>>> x
1674700755.0605464
>>> x
1674700755.0605464
>>> x
1674700755.0605464
>>> x
1674700755.0605464
>>> for i in range(5): print(time.time())
...
1674700912.1213877
1674700912.1214447
1674700912.1214585
1674700912.1214688
1674700912.1214786
>>> for i in range(5): print(x)
...
1674700755.0605464
1674700755.0605464
1674700755.0605464
1674700755.0605464
1674700755.0605464
As you can see if I call time.time multiple times the time changes, but if I assign it to x, then x always has the same value.
Below is the code I wrote to solve my problem:
import datetime
import time
from os import system
from sys import platform
import cursor
# print("What is the time and date of your event?")
# year = int(input("Year: "))
# month = int(input("Month: "))
# day = int(input("Day: "))
# hour = int(input("Hour: "))
# minute = int(input("Minute: "))
year = 2023
month = 1
day = 27
hour = 12
minute = 0
second = 00
date_entry = datetime.datetime(year, month, day, hour, minute, second)
print(f"The current date & time: {datetime.datetime.now()}")
print(f"The big day is: {date_entry}")
print()
print()
print(f"Tiff's Big day is going to be here soon:")
print()
while True:
event_count = date_entry - datetime.datetime.now()
event_hour = event_count.total_seconds() / 3600
event_min = ((event_hour % 1) * (60 / 100)) * 100
event_sec = ((event_min % 1) * (60 / 100)) * 100
print(f"{event_hour:.0f} Hours, {event_min:.0f} Minutes, {event_sec:.0f} seconds until big time!!!", end = "\r")
cursor.hide()
time.sleep(.5)

How to solve the total amount of seconds using python

I am learning python as a novice and I was asked to solve the total of seconds in the problem. I was given the format but it still seems that I can not get a hand of it. it keeps telling me that I didn't get the minute and seconds part
I tried this:
def get_seconds(hours, minutes, seconds):
return 3600*hours + 60*minutes + seconds
amount_a = get_seconds(3600*2 + 60*30 + 0*0)
amount_b = get_seconds(0 + 60*45 + 15)
result = amount_a + amount_b
print(result)
expecting to get it right as i think i imputed everything correctly but instead i was getting this:
Error on line 4:
amount_a = get_seconds(3600*2 + 60*30 + 0*0)
TypeError: get_seconds() missing 2 required positional arguments: 'minutes' and 'seconds'
Your function already does the job of multiplying hours by 3600 and minutes by 60. The point is for you to pass the hours, minutes, and seconds as separate arguments, like this:
amount_a = get_seconds(2, 30, 0) # 2 hours and 30 minutes
amount_b = get_seconds(0, 45, 15) # 45 minutes and 15 seconds
result = amount_a + amount_b # total seconds
print(result) # 11715
Your function is OK.
As the function computes the total from the 3 arguments.
When you call it, just pass the arguments.
def get_seconds(hours, minutes, seconds):
return 3600*hours + 60*minutes + seconds
amount_a = get_seconds(2, 30, 0)
amount_b = get_seconds(0, 45, 5)
result = amount_a + amount_b
print(result)

Add hours to workday in python

I need the following script to compute the working hours from 9 am to 6 pm, so that if I add 5 hours it will be added from 9 am the next day.
Example: if it is now 5 pm and I add 5 hours and the working day ends at 6 pm, the output would be: 13 hours.
17 + 1 = 18 and
9 + 4 = 13 hs
So far the script computes hours regardless of the labor restriction.
from datetime import datetime, timedelta
updated = ( datetime.now() +
timedelta( hours = 5 )).strftime('%H:%M:%S')
print( updated )
--22:12:00
Here you are:
workday_begin = time(9)
workday_end = time(18)
# compute workday length
workday_hours = datetime.combine(date.today(), workday_end) - datetime.combine(date.today(), workday_begin)
# this is timedelta from your example
duration_hours = timedelta(hours=17)
# ignore times longer than a workday
day_cnt = 0 # this could be used to know how many day we've skipped, not part of question tho
while duration_hours > workday_hours:
day_cnt += 1
duration_hours -= workday_hours
now = datetime.now()
# now = datetime(2021,12,10,11,25,16)
if workday_begin < now.time() < workday_end:
# now is in work-hours
if datetime.combine(date.today(), workday_end) - now < duration_hours:
# duration would exceed work-hours, jumping to next day
day_cnt += 1
duration_hours -= (datetime.combine(date.today(), workday_end) - now)
updated = datetime.combine(date.today(), workday_begin) + duration_hours
else:
# everything is fine, just add hours
updated = now + duration_hours
else:
# now is not in work-hours. Add remaining duration to workday begin
updated = datetime.combine(date.today(), workday_begin) + duration_hours
# keep just a time part
updated = updated.time().strftime('%H:%M:%S')
print( updated )
I hope I understood your question.

Issues with displaying time results in Python

I have written a code to take in a running pace value (min/km), convert it to speed (km/hr) and then depending on the slope gradient and whether the direction of travel is up or downhill the lost speed is calculated (km/hr). The new running speed is then displayed along with the new running pace and the time your route is altered by.
The issue is when I input a pace such as 3:50 (min/km) with an uphill slope of 1% the new running pace is 3:60 (min/km). How do I get the script to tick over to 4:00 in this case? Also if 3:55 (min/km) is input the new running pace given is 4:5 (min/km) when it should read as 4:05 (min/km). How do i edit this?
The script is:
import math
print('Q1')
SurveyPace = input("Running Pace (min/km): \n "). split(":")
SurveyPace = float(SurveyPace[0])*60 + float(SurveyPace[1])
Speed = 3600/SurveyPace
print("Original running speed =","%.2f" % round(Speed,2), 'km/hr')
print("--------------------------------------------------------")
print('Q2')
SlopeDirection = int(input('For Uphill press 1 \nFor Downhill press 2 \n '))
print("--------------------------------------------------------")
print('Q3')
SlopeGradient = float(input('Percentage gradient(without the % symbol)?\n '))
print("--------------------------------------------------------")
print('CALCULATED RESULTS')
print("--------------------------------------------------------")
if SlopeDirection == 1:
Change = - 0.65 * SlopeGradient
if SlopeDirection == 2:
Change = + 0.35 * SlopeGradient
print ('This route alters your speed by \n', Change,'km/hr')
print("--------------------------------------------------------")
AdjustedSpeed = Speed + Change
AdjustedPace = 3600/AdjustedSpeed
PaceSecs = round(AdjustedPace % 60)
PaceMins = math.floor(AdjustedPace/60)
print("New running speed is \n","%.2f" % round(AdjustedSpeed,2), 'km/hr')
print("--------------------------------------------------------")
print("New running pace is \n", str(PaceMins) + ":" + str(PaceSecs), 'min/km')
print("--------------------------------------------------------")
print("This route alters your pace by \n", int(PaceSecs + (PaceMins*60)) - SurveyPace, "sec/km") #Prints the time change incured
print("--------------------------------------------------------")
Thanks
You can do this with the built-in function divmod:
# Round the AdjustedPace to seconds
AdjustedPace = round(3600/AdjustedSpeed)
minutes, seconds = divmod(AdjustedPace, 60)
print(minutes)
print(seconds)
This will lead to:
#Pace = 3:50
#4
#0
#Pace = 3:55
#4
#5
I would do this with timedelta objects from datetime:
import datetime
inp = raw_input('Enter your pace in minutes per km (min:km):')
mins, kms = inp.split(':')
time = datetime.timedelta(minutes=int(mins))
If you enter 60 minutes, for example, will give you:
> time
datetime.timedelta(0, 3600)
And then you can perform math operations on it and it stays correct:
> time / 2
datetime.timedelta(0, 1800)
Or if you want minutes just divide it by 60, hours divide it by 3600. You can also add and subtract timedelta objects from each other, or from datetime objects if you want timestamps. Or if your divisor leaves a remainder:
> new = time / 17
> new
datetime.timedelta(0, 3600)
> new.seconds
200
> new.microseconds
764706
Which you could then use to round if you wanted. It's a good way to make sure your time always stays accurate.

Long Count Mayan Date in Python

I need to compile a program that can convert a Gregorian date to a Mayan one. I also need to use 01/01/1970 as a reference date.
The following auxiliary functions work accordingly and have no mistakes.
# turns dates into tuples
def dmj(date):
"""
>>> dmj('01/01/1970')
(1, 1, 1970)
>>> dmj('00012+00012+02012')
(12, 12, 2012)
"""
tup = ()
for i in date:
if i.isdigit() == False and i != ' ':
date = date.replace(i, ' ')
number_str = ''
for i in date:
number_str += i
if i == ' ':
number = int(number_str)
tup += (number,)
number_str = ''
tup += (int(number_str),)
return tup
# counts days that have passed since 01/01/1970
def daysPassed(date):
"""
>>> daysPassed('01/01/1970')
0
>>> daysPassed('20-7-1988')
6775
>>> daysPassed('00012+00012+02012')
15686
"""
from datetime import date
tup = dmj(date)
begin = date(1970, 1, 1)
end = date(tup[2], tup[1], tup[0])
passed = abs(end - begin)
return passed.days
My idea was to first calculate how many days have passed since the beginning of this pictun (20 baktuns long) in 01/01/1970 and then added the days passed since then according to the given date.
In the Mayan calendar a day is refered to as a kin. Their periods (within one pictun) are as follows:
20 kin = 1 uinal; 18 uinal = 1 tun; 20 tun = 1 katun; 20 katun = 1 baktun
In the long count notation the Mayan date for 01/01/1970 is '12.17.16.7.5'. Baktun are written first, then katuns, etc... Mayan dates start from 0. Basically the first kin of a uinal is number zero and the last one number 19, twenty in total.
I've first compiled the following:
def mayanDate(date, separation='')
"""
>>> mayanDate('01/01/1970')
'12/17/16/7/5'
>>> mayaDate('20-7-1988', separator='/')
'12/18/15/4/0'
>>> mayaDate('00012+00012+02012', separator='-')
'12-19-19-17-11'
>>> mayaDate('21 12 2012', separator='+')
'13+0+0+0+0'
>>> mayaDate('26.03.2407')
'14.0.0.0.0'
"""
days = daysPassed(date) + 13 * 144000 + 18 * 7200\
+ 17 * 400 + 8 * 20 + 6
baktun = str((days //((20 **3) * 18)) - 1)
days = days % ((20 **3) * 18)
katun = str((days //((20 **2) * 18)) - 1)
days = days % ((20 **2) * 18)
tun = str((days // (20 **2)) - 1)
days = days % (20 **2)
uinal = str((days // 20) - 1)
days = days % 20 - 1
kin = str(days)
mayanlist = [baktun, katun, tun, uinal, kin]
for i in date:
if i.isdigit() == False and separator == '':
separator = i
break
mayandate = separator.join(mayanlist)
return mayandate
For some strange reason only 01/01/1970 returns the correct Mayan long notation, despite counting from the beginning of an entire pictun (7,900 years in length!). For all other dates it seems to advance too fast through the calendar, despite my second auxiliary function returning the correct values (even for millennia into the future).
I wonder where's the mistake. For instance mayanDate('20-7-1988') returns '12-18-15-6-0' instead of '12-18-15-4-0' and mayanDate('21 12 2012') returns '13 0 1 12 0' instead of '13 0 0 0 0'.
The issue you're seeing with the negative 1 kin for date '15/01/1970' is due to the removal of one from every date ordinal during the calculation. Taking x%20 will always return a value between 0 and 19 inclusive. Taking one from the result necessarily shifts this range to -1 to 18 inclusive.
The number added to the result of daysPassed(date) seems to be a conversion of the long form of 1/1/1970, with one added to each digit. I'm assuming this has been done to counter the fact that the Mayan calendar starts counting at zero, but is unnecessary. The Mayan date 0.0.0.0.1.5 counts 25, not 151646. This doesn't appear to be the source of the error though, since removing this issue from my own code, I still get the same results as described for the 20-7-1988 and 21-12-2012.
I finally rooted out the error when I went back and switched out all the magic numbers in my code for named constants (it makes the code far easier to debug, read and maintain). You state there are 18 uinal in a tun, and 20 tun in a katun, but these numbers are reversed in the code.
Here's my code:
def mayanDate(date_str, seperation=','):
days_in_kin = 1
kin_in_uinal = 20
uinal_in_tun = 18
tun_in_katun = 20
katun_in_baktun = 20
days_in_uinal = days_in_kin * kin_in_uinal
days_in_tun = days_in_uinal * uinal_in_tun
days_in_katun = days_in_tun * tun_in_katun
days_in_baktun = days_in_katun * katun_in_baktun
days_1970 = 12 * days_in_baktun \
+ 17 * days_in_katun\
+ 16 * days_in_tun\
+ 7 * days_in_uinal\
+ 5 * days_in_kin
total_days = daysPassed(date_str) + days_1970
baktun = total_days // days_in_baktun
total_days -= baktun * days_in_baktun
katun = total_days // days_in_katun
total_days -= katun * days_in_katun
tun = total_days // days_in_tun
total_days -= tun * days_in_tun
uinal = total_days // days_in_uinal
total_days -= uinal * days_in_uinal
kin = total_days // days_in_kin
print seperation.join(map(str, (baktun, katun, tun, uinal, kin)))
(I subtracted the previous calculations from total days, rather than using a modulo operator, since I feel it's cleaner. I guess it's a matter of personal preference.)
I may have found something.
>>>mayanDate('15/01/1970')
'12/17/16/8/-1'
Obviously not possible. -1 has to be 19 here and 8 has to be 7. It seems to turn month too early. Still not out why 01/01/1970 remains correct here. No idea what's so special about that date.

Categories