if logic breaks when calculating time over multiple days - python

My code below - yes, ugly. I am learning python. It works when the start/end dates are both the same day.
When start = 2017,6,15 6:00 & end = 2017,6,16 6:00
The if statement that gets applied is if start < 6am. Can someone explain why? It does recognize that 1 day is the duration.
from datetime import datetime, date, time
def babysitting():
(st_yr,st_mon,st_day) = [int(s) for s in input("Enter the start date in the format: YYYY,M,D: ").split(',')]
(st_hr,st_min) = [int(s) for s in input("Enter the start time in 24hr format -> HH:MM: ").split(":")]
(e_yr,e_mon,e_day) = [int(s) for s in input("Enter the end date in the format: YYYY,M,D: ").split(',')]
(e_hr,e_min) = [int(s) for s in input("Enter the end time in 24hr format -> HH:MM: ").split(":")]
st_date = date(st_yr,st_mon,st_day)
st_time = time(st_hr,st_min)
end_date= date(e_yr,e_mon,e_day)
end_time = time(e_hr,e_min)
start = datetime.combine(st_date,st_time)
end = datetime.combine(end_date,end_time)
ninePM = datetime.combine(end_date, time(21,00))
sixAM = datetime.combine(end_date, time(6,00))
if start >= sixAM:
if end <= ninePM:
normal_rate_duration = end - start
normal_rate_seconds = normal_rate_duration.total_seconds()
normal_rate_billing = round(((normal_rate_seconds / 60) / 60) * 2.5,2)
print("Cost for babysitting is: $", normal_rate_billing)
elif end > ninePM:
normal_rate_duration = ninePM - start
reduced_rate_pm_duration = end - ninePM
normal_rate_seconds = normal_rate_duration.total_seconds()
normal_rate_billing = round(((normal_rate_seconds / 60) / 60) * 2.5,2)
reduced_rate_pm_seconds = reduced_rate_pm_duration.total_seconds()
reduced_rate_pm_billing = round(((reduced_rate_pm_seconds / 60) / 60) * 1.75,2)
print("Cost for babysitting is: $", normal_rate_billing + reduced_rate_pm_billing)
if start < sixAM:
if end <= ninePM:
reduced_rate_am_duration = sixAM - start
reduced_rate_am_seconds = reduced_rate_am_duration.total_seconds()
reduced_rate_am_billing = round(((reduced_rate_am_seconds / 60) / 60) * 1.75,2)
normal_rate_duration = end - sixAM
normal_rate_seconds = normal_rate_duration.total_seconds()
normal_rate_billing = round(((normal_rate_seconds / 60) / 60) * 2.5,2)
print("Cost for babysitting is: $", normal_rate_billing + reduced_rate_am_billing)
elif end > ninePM:
reduced_rate_am_duration = sixAM - start
reduced_rate_am_seconds = reduced_rate_am_duration.total_seconds()
reduced_rate_am_billing = round(((reduced_rate_am_seconds / 60) / 60) * 1.75,2)
normal_rate_duration = ninePM - sixAM
normal_rate_seconds = normal_rate_duration.total_seconds()
normal_rate_billing = round(((normal_rate_seconds / 60) / 60) * 2.5,2)
reduced_rate_pm_duration = end - ninePM
reduced_rate_pm_seconds = reduced_rate_pm_duration.total_seconds()
reduced_rate_pm_billing =round(((reduced_rate_pm_seconds / 60) / 60) * 1.75,2)
print("Cost for babysitting is: $", normal_rate_billing + reduced_rate_am_billing + reduced_rate_pm_billing)
babysitting()

your if checks whether or not the start time was earlier than 6am on the end date, which of course it will be (it's some time the day before or something like that). you need to check if st_time is earlier than 6am (regardless of date, or on the st_date date).

Related

python to mysql query

im trying to convert this trending algorithm to mysql query
# Rewritten code from /r2/r2/lib/db/_sorts.pyx
from datetime import datetime, timedelta
from math import log
epoch = datetime(1970, 1, 1)
def epoch_seconds(date):
td = date - epoch
return td.days * 86400 + td.seconds + (float(td.microseconds) / 1000000)
def score(ups, downs):
return ups - downs
def hot(ups, downs, date):
s = score(ups, downs)
order = log(max(abs(s), 1), 10)
sign = 1 if s > 0 else -1 if s < 0 else 0
seconds = epoch_seconds(date) - 1134028003
return round(sign * order + seconds / 45000, 7)
mysql table have
up_count down_count created_date
is this possible ?
i found this ,but this have a bug if the down_vode is bigger then you have LOG10(Zero) and this will crash
ORDER BY
LOG10(ABS(thumbs_up - thumbs_down) + 1) * SIGN(thumbs_up - thumbs_down)
+ (UNIX_TIMESTAMP(created) / 300000) DESC
LIMIT 100
This is the MySql translation of you function:
SELECT ROUND((INTERVAL(up_count - down_count, -1, 0, 1) - 2) * LOG(GREATEST(ABS(up_count - down_count), 1), 10) + UNIX_TIMESTAMP(created_date) / 45000 , 7) FROM your_table

Round time in python odoo

I use below example for round time in odoo.
#api.one
#api.depends('start','finish','pause')
def total(self):
for rec in self:
time1 = datetime.strptime(rec.start, "%Y-%m-%d %H:%M:%S")
time2 = datetime.strptime(rec.finish, "%Y-%m-%d %H:%M:%S")
rec.total_time = round(((time2 - time1).seconds / float(60*60) - self.pause))
For example:
if start = 07:57:21 , finish = 16:25:36, pause = 1 get result 7 hours
if start = 07:57:34 , finish = 16:28:42, pause = 1 get result 8 hours
First and second time different is 3 minutes but in result that is one hours!
How change round if total time >= 7 hours 30 minutes 01 second I need result 8 in other solution 7.5 (7 hours and 30 minutes)
For "%Y-%m-%d %H:%M:%S" you can use DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
For your problem you can use round(x, n). Example:
round(7.4, 0) = 7
round(7.5, 0) = 8
round(7.5, 1) = 7.5
Here you need n = 1 for 7.5 and n=0 for the 'standard' round. You can check 7.5 with ((7.5 - 0.5) % 1) == 0 and convert it from boolean to int directly with int()
The general solution is:
#api.one
#api.depends('start','finish','pause')
def total(self):
for rec in self:
time1 = datetime.strptime(rec.start, DEFAULT_SERVER_DATETIME_FORMAT)
time2 = datetime.strptime(rec.finish, DEFAULT_SERVER_DATETIME_FORMAT)
total_time = (time2 - time1).seconds / float(60*60) - self.pause
rec.total_time = round(total_time, int(((total_time - 0.5) % 1) == 0))
#api.one
#api.depends('start','finish','pause')
def total(self):
for rec in self:
time1 = datetime.strptime(rec.start, DEFAULT_SERVER_DATETIME_FORMAT)
time2 = datetime.strptime(rec.finish, DEFAULT_SERVER_DATETIME_FORMAT)
total_time = (time2 - time1).seconds / float(60*60) - self.pause
total_time = 2*total_time
if 2*total_time%1 <=0.5 :
res = round(total_time)
else :
res = round(2*total_time)
rec.total_time = res

Add function names to a string in Python

I'm just beginning to learn Python on my own, and I'm trying to write a code that will calculate the end time of a jog.
My code so far looks as follows:
def elapsed(t):
t = raw_input('Enter time (hh:mm:ss): ')
th, tm, ts = t.split(':')
return int(ts) + int(tm) * 60 + int(th) * 3600
def mile(m):
m = raw_input('How many miles? ')
return int(m)
start = elapsed('start')
warmup = elapsed('warmup')
wmile = mile('wmile')
tempo = elapsed('tempo')
tmile = mile('tmile')
cooloff = elapsed('cooloff')
cmile = mile('cmile')
hour = (start + warmup * wmile + tempo * tmile + cooloff * cmile) // 3600
minute = (start + warmup * wmile + tempo * tmile + cooloff * cmile - hour * 3600) // 60
second = (start + warmup * wmile + tempo * tmile + cooloff * cmile - hour * 3600) % 60
print('Your run ended at %02d:%02d:%02d' % (hour, minute, second))
In this code, the time prompts are all the same: "Enter time (hh:mm:ss):" I want each prompt to refer to its variable name, e.g., "Enter start time (hh:mm:ss)" or "Enter time (hh:mm:ss): (warmup)". Is there a way to do this?
Note: While this may technically be a duplicate, I have examined the similar questions, but decided that both the questions and the answers provided were on the more unspecific side, and therefore decided to ask my question anyway.
Yes, use the input to your function elapsed(t).
Right now it's being overwritten with the return from raw_input()
def elapsed(t):
t1 = raw_input('Enter time (hh:mm:ss): ({0})'.format(t))
th, tm, ts = t1.split(':')
return int(ts) + int(tm) * 60 + int(th) * 3600
or
def elapsed(t):
t1 = raw_input('Enter time (hh:mm:ss): (%s)' % t))
th, tm, ts = t1.split(':')
return int(ts) + int(tm) * 60 + int(th) * 3600
def enter_time(specify_string):
print("Please enter the", specify_string, 'time in format hh:mm:ss > ', end='')
hh, mm, ss = input().split(':')
return (hh, mm, ss)
start_time = enter_time('start')
finish_time = enter_time('finish')
>>>Please enter the start time in format hh:mm:ss >13:32:34
>>>Please enter the finish time in format hh:mm:ss >12:21:21
>>>start_time
(13, 32, 34)
Now you can call the function with string arguments in the function call, and it will generalise the function for different requirements.
It is better to move the time between functions in a more readable format, such as a tuple. You can make more functions, eg:
- Test valid time entered
- Convert tuple to seconds for calculations
- Convert seconds back to tuple format
ect.
Let me know if I misunderstood you.

Adding x seconds worth of time onto a string variable time of HH:MM

I'm trying to work out a way to make a new variable AUTOMATIC_END_TIME based on adding the minimum amount of time onto the start time but I can't figure out the way to allow START_TIME to be turned into a time that can then have time added onto it.
So far my script has the following:
from time import sleep
from datetime import datetime, timedelta
START_TIME = "19:18"
END_TIME = "19:25"
LOGA = ["one", "two"]
TIME_DIFFERENCE = datetime.strptime(END_TIME, "%H:%M") - datetime.strptime(START_TIME, "%H:%M")
TIME_DIFFERENCE = TIME_DIFFERENCE.seconds
if len(LOGA) * (60 * (5 + 1)) >= TIME_DIFFERENCE:
print "Show minimum end time"
AUTOMATIC_END_TIME = "" # Should come out as 19:30
The current script shouldn't change at all except for AUTOMATIC_END_TIME which should be START_TIME + (60 * (5 + 1) It should come out as 19:30
>>> (datetime.strptime(START_TIME, "%H:%M") + timedelta(minutes=12)).strftime('%H:%M')
'19:30'
from time import sleep
from datetime import datetime, timedelta
START_TIME = "19:18"
END_TIME = "19:25"
LOGA = ["one", "two"]
TIME_DIFFERENCE = datetime.strptime(END_TIME, "%H:%M") - datetime.strptime(START_TIME, "%H:%M")
TIME_DIFFERENCE = TIME_DIFFERENCE.seconds
if len(LOGA) * (60 * (5 + 1)) >= TIME_DIFFERENCE:
print "Show minimum end time"
AUTOMATIC_END_TIME = (datetime.strptime(START_TIME, "%H:%M") + timedelta(minutes=12)).strftime('%H:%M')
print AUTOMATIC_END_TIME

ZeroDivisionError: float division error in python

I'm working on my python script for xbmc media application so I can update the text label with the percent string. I have set the label text with "0%" for the start, but I have no idea how to update the label text with "1%", "10%", "20%" and so on.
When I try this:
progressStartTime = datetime.datetime.now()
delta = datetime.datetime.now() - progressStartTime
secondsLeft = int(delta.seconds) / float(percentageComplete) * (100.0 -
percentageComplete)
if secondsLeft > 30:
secondsLeft -= secondsLeft % 10
self.setControlLabel(self.main_loading_time_left, "" % secondsLeft)
I'm having trouble with update the text in the label where I'm getting an
error. The error I'm getting is: ZeroDivisionError: float division
The error are jumping on this line:
secondsLeft = int(delta.seconds) / float(percentageComplete) * (100.0
- percentageComplete)
Can you please help me how I can update the text in the label with the percent string?
Edit: Here is the update code:
percentageComplete = 0
if percentageComplete < 1:
self.getControl(4202).setLabel("1%")
progressStartTime = datetime.datetime.now()
delta = datetime.datetime.now() - progressStartTime
secondsLeft = int(delta.seconds) * (100.0 - percentageComplete)
if percentageComplete > 1:
secondsLeft -= secondsLeft % 10
self.getControl(4202).setLabel(secondsLeft + "%")
#self.setControlLabel(self.main_loading_time_left, "%" % secondsLeft)
You can't determine what time is left when you're at 0%. Exclude that case with a if case.

Categories