#๐Ÿ”’ i made this timer of sorts that sends notifcations, and it asks for input twice and idk why

382 messages ยท Page 1 of 1 (latest)

gray scrollBOT
#

@tribal lintel

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

tribal lintel
#

any feedback would be appreciated

idle isle
#

.

#

its because

#

.

#

.

#

idk

#

thats my guess

karmic sparrow
#

asks me once and has errors

#
Give me the time you want in a 24 hour format (such as xx:xx): aa-ff
b
Are you sure you entered the time wanted correctly?
Give me the time you want in a 24 hour format (such as xx:xx): 12:12
if hours_till_ring == 0:
       ^^^^^^^^^^^^^^^
NameError: name 'hours_till_ring' is not defined```
#

if enter correctly first time:

#
Give me the time you want in a 24 hour format (such as xx:xx): 12:12
b
Your timer will ring in 6 hour(s)
#

if you are using a proper IDE you should clearly see the issue as it will be highlighted with hints

tribal lintel
#

yes but when time reaches 30 mins before or same time it asks again

#

using pycharm

karmic sparrow
#

then you must have noticed it telling you you screwed up

tribal lintel
#

the issue with the asking twice was here before that

karmic sparrow
tribal lintel
#

idk if that makes sense

karmic sparrow
#

it doesn't run fine; it throws an error

#

because you are using a variable that doesn't exist if they type bad input once

#

there are more issues

#

for example you are using int wrong here

tribal lintel
#

like? any feedback would be appreciated

#

ah

#

how so?

karmic sparrow
#

run this to see why you don't need all that

#
from datetime import datetime
current_time = datetime.now()
print(current_time.hour)
#

you don't need all that parsing and int stuff

tribal lintel
#

hmmm

karmic sparrow
#

maybe this will be better to start anew

#

I can help you out since your error part is also wrong

tribal lintel
#

yeahhh

karmic sparrow
#

and it will fail if they enter bad stuff twice

#

(or in your case with the bug, even once)

tribal lintel
#

it would be better to burn my computer and throw myself into a river

karmic sparrow
#

nah

#

we all start like this don't worry

#

keep all that code and start a new file

#

I will walk you through; will be easy and fun

tribal lintel
#

the thing i dont understand is it runs fine, except the thing where it asks twice

#

will do

#

1 sec

#

ok new file, i import datetime

#

right

karmic sparrow
#

from datetime import datetime

#

not *

tribal lintel
#

ye

karmic sparrow
#

so

tribal lintel
#

thas what i mean

karmic sparrow
#

the first thing we want to get is

#

we want user to give us a time

#

we don't want strings and numbers and whatever, and we don't want to continue until we have our valid answer

#

that is done by using a loop

#

there are common structures for this. I can tell you both or just tell you one; up to you

tribal lintel
#

id be interested in learning both

karmic sparrow
#

ok

#

so one is done by using a loop while True

#
while True:
  # try do do something
  # if successful, break
#

this is ugly because it's kind of weird to loop true

#

however, it has an advantage over the other one

#

the other one is this

tribal lintel
#

which is?

karmic sparrow
#
# try to do something
while # not successful:
  # try to do something
#

the advantage of this way is your loop makes more sense

#

the disadvantage is you have to write the thing out twice

#
answer = input(...)
while answer not ...:
  print('bad boy')
  answer = input(...)
tribal lintel
#

if u was me which one would u use

karmic sparrow
#

see what I mean

#

they are both equally good to be honest

#

it's just a style choice in this case

#
while True:
  answer = input(...)
  if answer is correct:
    break
  print('bad boy')
#

whichever one looks more clear to your future self

tribal lintel
#

the first one

karmic sparrow
#

ok

tribal lintel
#

while true and if statement

karmic sparrow
#

ok so build that very basic structure

#

only this time, we are going to force the input to be right immediately, rather than having to convert it later

tribal lintel
#

no wait this way is strange

#

i no likey

#

the second one a bit clearer tbh

#

second one will stop automatically once the input is correct right?

#

so no need for an if statement

karmic sparrow
#

everything will function exactly the same 100%

#

it is only a style choice in this case

#

let's just stick with the while True for now

tribal lintel
#

will do

karmic sparrow
#

no need to get bogged down

#

so what we want to do is immediately convert their input into a datetime

tribal lintel
#

like in a 24h format?

karmic sparrow
#

because what we really are asking is, how long from now do you want to tell us

#

so what we want to end up doing is

#

adding what they say to now, to find out which future time they are referring to

#

make sense?

tribal lintel
#

sorta

#

if u could give me an example that would be great

#

im a bit slow dont mind me

karmic sparrow
#

I am going to walk you through it

#

I just want you to understand what's happening before we do it

#

the key here is that you should get what you are actually looking for

#

what you are actually looking for is not some xx:yy: string, nor some vague time string or whatever

#

what you actually want is "how long from now do you want"

#

so in order to do that we will find now, and add what they said to it to remember what they said as an actual time

#

is that making sense

tribal lintel
#

so basically take datetime.now (hours and minutes) and add whatever the user says to it to find future time?

karmic sparrow
#

exactly

#

so datetime has a tool for this

#

it's called timedelta

#

so go ahead and import that too

#

from datetime import datetime, timedelta

#

we know that they are supposed to do HH:MM in their input

#

there are a few ways to go from here but to keep it simple we can just split it by ':' and everything on the left is hours and right is minutes

#
from datetime import datetime, timedelta
while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    hours, minutes = time_wanted.split(':')
tribal lintel
#

yurr

karmic sparrow
#

does that mean you're lost or you're with me

tribal lintel
#

im with ya

karmic sparrow
#

ok

#

so you already know how to get now

#

datetime.now()

tribal lintel
#

was just making sure i understood last line correctly

karmic sparrow
#

and now all we want to do is add their hours and their minutes to now

tribal lintel
#

yeah but now will provide the whole thing including seconds date ect

karmic sparrow
#

don't worry about that

tribal lintel
#

ok

karmic sparrow
#

so we just use timedelta, it is very simple

tribal lintel
#

btw thank you for helping, ur great :D

karmic sparrow
#

the syntax is datetime + timedelta(hours=hours, minutes=minutes etc)

#

so in this case we would do this

#
from datetime import datetime, timedelta
while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    hours, minutes = time_wanted.split(':')
    time_wanted = datetime.now() + timedelta(hours=int(hours), minutes=int(minutes))
#

now if we print datetime.now() and time_wanted, we will see time_wanted is offset by their input

#
Give me the time you want in a 24 hour format (such as xx:xx): 12:12
2024-08-24 19:17:31.050646
2024-08-25 07:29:31.050646
#

so now we know two things - when is it now, and when do they want to do stuff

#

and we no longer have to format stuff

karmic sparrow
#

see the output

#

the first datetime was .now() when I ran it a few minutes ago

#

the second datetime is that time + 12:12

#

is that right or did you want them to put in the absolute time, like an alarm?

#

oh sorry I guess you wanted them to put in the absolute time?

tribal lintel
#

i apologize u lost me

#

by absolute time u mean?

karmic sparrow
#

what is the input they are putting in

#

the amount of time to wait for the alarm? or the exact time the alarm should go off

tribal lintel
#

oh the time to wait

#

ohhhh, nvm time alarm to go off

#

thats what i do

#

got it

karmic sparrow
#

ok so you want them to put in 06:00 and that means "the next time it is 6:00 ring the alarm" right?

tribal lintel
#

yes

karmic sparrow
#

ok that's easier then hang on

#

then you really just need this

#
from datetime import datetime

while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    hours, minutes = time_wanted.split(':')
    hours = int(hours)
    minutes = int(minutes)
#

so now we have the ability to see two things - what time is it now, and what hour and minute do they want the alarm to go off at

#

but this all assumes they put in the right input

#

so what we want to do is add an error check to make sure everything is happy before we continue on

#

making sense?

tribal lintel
#

yes

karmic sparrow
#

ok so there are two areas of potential error here (that we care about)

#

they could be missing a : , in which case the split will fail

#

they could have put in random garbage, in which case the int( will fail

#

to figure out which errors those will be, you can simply try to do them and see what happens

#
Give me the time you want in a 24 hour format (such as xx:xx): sdfsdfg
ValueError: not enough values to unpack (expected 2, got 1)
tribal lintel
#

couldnt we use a try except with Value error

karmic sparrow
#

ValueError is one

tribal lintel
#

yes

karmic sparrow
#

and valueerror is also for int

#

so that means all we need to do is wrap those three lines in the try except for valueerror

#
from datetime import datetime

while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    try:
        hours, minutes = time_wanted.split(':')
        hours = int(hours)
        minutes = int(minutes)
    except ValueError:
        print('I said 24 hour format (such as xx:xx) ...')
        continue
tribal lintel
#

from hours,minutes to last line right?

#

yes

karmic sparrow
#

so now we've eliminated errors

#

but we still haven't validated the data

#

do we want them to be able to do this? 99999999:99999999

tribal lintel
#

nope, we wanna set a character limit?

karmic sparrow
#

what about 99:99

tribal lintel
#

no

#

2 high

#

like me

karmic sparrow
#

seems like we actually want 0-23:0-59

#

right?

tribal lintel
#

yes

karmic sparrow
#

great so let's just check what they put in and make sure each is in those ranges

tribal lintel
#

idk if there is a faster way of doing this but we chan check hours and minutes seperately to make sure its within range

karmic sparrow
#
    if not (0 < hours < 24 and 0 < minutes < 60):
        print('0-23 hours and 0-59 minutes please!')
        continue
#

this little shortcut checks multiple things at once:

#
0 < 1 < 2
tribal lintel
#

oh

#

yes

karmic sparrow
#

that is true

#

so this little check makes sure they are in the right range

tribal lintel
#

was gonna do 2 seperate ifs but thats much faster

karmic sparrow
#

so now we have made sure there are no errors and the data is how we want it

#

so as of now we know we have good data

tribal lintel
#

yeap

karmic sparrow
#

all we need to do now is just break the loop

#
from datetime import datetime

while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    try:
        hours, minutes = time_wanted.split(':')
        hours = int(hours)
        minutes = int(minutes)
    except ValueError:
        print('I said 24 hour format (such as xx:xx) ...')
        continue

    if not (0 < hours < 24 and 0 < minutes < 60):
        print('0-23 hours and 0-59 minutes please!')
        continue
    break
#

so now we can do stuff, knowing that hours and minutes is valid data

tribal lintel
#

yes

#

through time_wanted we check if its equal to datetime.now?

#

but that wouldnt work would it

karmic sparrow
#

well I'm just following your code now

#

you want to be able to print how long it will be

#

we can do it a more advanced way but there's no point really so let's just do it your way

#

(but simpler)

#
hours_till_ring = abs(datetime.now().hour - hours)
tribal lintel
#

makes sense

#

hours undefined

karmic sparrow
#

but the issue is going to become this abs stuff you are doing

tribal lintel
#

how come?

karmic sparrow
#

it's not undefined if you are using my code

#

oh you mean pycharm warning

#

that's because technically another error can happen

#

you can avoid that by putting a hours = 0 and minutes = 0 above the loop if you like

tribal lintel
#

nah its chill

karmic sparrow
#
from datetime import datetime

hours = 0
minutes = 0
while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    try:
        hours, minutes = time_wanted.split(':')
        hours = int(hours)
        minutes = int(minutes)
    except ValueError:
        print('I said 24 hour format (such as xx:xx) ...')
        continue

    if not (0 < hours < 24 and 0 < minutes < 60):
        print('0-23 hours and 0-59 minutes please!')
        continue
    break

hours_till_ring = abs(datetime.now().hour - hours)
minutes_till_ring = abs(datetime.now().minute - minutes)
tribal lintel
#

ohh

karmic sparrow
#

the problem you gonna have though is your use of abs is not right

#

right now it's 45 minutes past the hour

#

if I put an alarm for next hour, 43 minutes, your script will tell me 1 hour and 2 minutes

#

even though that's not correct

#

see what I mean?

tribal lintel
#

yeah

karmic sparrow
#

so this is why timedelta exists

#

because the real way to calculate this is to sit there and do math with the number 60 to figure everything out

#

if minutes < now.minutes: 60 - minutes.. . etc

#

so long story short it's still better to make an actual datetime from their input and let timedelta do that for us

tribal lintel
#

hmm

#

give me a sec catching up

karmic sparrow
#

you can see the problem by putting in a minute that is lower than the current minute

tribal lintel
#

ok ye makes sense

karmic sparrow
#

the same issue will be there for hours

#

if it's 11pm now and I put 10pm, your script will tell me I need to wait 1 hour

#

even though it's actually 23 hours away

#

so the math becomes 24 - hours if it's lower than current hour, else hours - current hour

#

and 60 - minutes if lower than current minute, else minutes - current minutes

#

in your case I guess we can just do that

#

all this is just to print out that message by the way

tribal lintel
#

ouff

#

should consider becoming a monk

#

im a bit lost give me a sec to catch u

karmic sparrow
#

right now it's 19:54 here

#

how many minutes (only minute) do I need to wait for 20:53?

#

6 until it becomes 0 again

#

then another 53 for it to become 53

#

so that's.. 59 total

#

so 60 - now, + minutes

#

but even this is wrong because we didn't add one to hours

tribal lintel
#

any way to dumb it down a bit?

#

cuz im a bit confused

karmic sparrow
#

you are pretending minutes and hours are separate

#
Give me the time you want in a 24 hour format (such as xx:xx): 20:56
now 2024-08-24 19:57:30.798471
wait hours 1
wait minutes 59
#

this is telling me I need to wait 1 hour and 59 minutes for what is actually 59 minutes away

tribal lintel
#

yes

karmic sparrow
#

this is the type of issue that comes up when you just do straight math on minutes and then separately on the hours

tribal lintel
#

oh

#

so what is done to fix that

karmic sparrow
#

we actually want this kind of output

#
Give me the time you want in a 24 hour format (such as xx:xx): 23:00
now 2024-08-24 19:59:59.556266
wait hours 3
wait minutes 1
#

you can see that (ignoring seconds), we should wait 3 hours and 1 minute from 19:59 to 23:00

#

so here is the updated version

#
from datetime import datetime

hours = 0
minutes = 0
while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    try:
        hours, minutes = time_wanted.split(':')
        hours = int(hours)
        minutes = int(minutes)
    except ValueError:
        print('I said 24 hour format (such as xx:xx) ...')
        continue

    if not (0 <= hours < 24 and 0 <= minutes < 60):
        print('0-23 hours and 0-59 minutes please!')
        continue
    break

current = datetime.now()
temp_hours = hours
if minutes < current.minute:
    minutes_till_ring = (60 - current.minute) + minutes
    temp_hours -= 1
else:
    minutes_till_ring = minutes - current.minute

if temp_hours < current.hour:
    hours_till_ring = (24 - current.hour) + temp_hours
else:
    hours_till_ring = temp_hours - current.hour
#

first, we record the current hours into a different variable

#

if they said a minute value less than the current minute, that means we actually need to subtract an hour from our temporary hour

#

11:59 -> 12:58

#

since 58 is lower than 59, that means we actually remove an hour for the math

tribal lintel
#

hmm

karmic sparrow
#

how long from 11 to 12

#

1 hour

#

how long from 11:01 to 12:02

tribal lintel
#

1m

karmic sparrow
#

1 hour 1 minute

tribal lintel
#

1.1m

karmic sparrow
#

how long from 11:15 to 12:14

#

12 - 11 = 1 hour

tribal lintel
#

59

karmic sparrow
#

what happened to the hour?

#

(you removed it)

#

it's no longer "1 hour and x minutes"

#

it's just "x minutes"

#

hence, temp_hours -= 1

tribal lintel
#

yes

karmic sparrow
#

ok so now we know how many hours and minutes until the alarm

#

we can just add those prints as they are

#

and now the loop

#

all we really need to do is

#

check if the hour and minute match what they wanted

#

(and check if it's 30 minutes beforehand)

#

and print something based on those, or do nothing (but wait so we don't eat cpu)

tribal lintel
#

mhm

karmic sparrow
#
while True:
    current = datetime.now()
    if current.hour == hours and current.minute == minutes:
        print('ALARM!')
        break
#

we need a sleep so it doesn't hog our resources

#

so we need to import time

#

and then

#
while True:
    current = datetime.now()
    if current.hour == hours and current.minute == minutes:
        print('ALARM!')
        break
    time.sleep(1)
tribal lintel
#

from time import sleep then

#

so we dont import everything

karmic sparrow
#

you can do that yeah

#

in this case it's more normal to import time

#

for reasons you won't care about (there are other sleeps people use)

#

so for the 30 minute warning, that's a bit harder since we're not using proper datetime/timedelta objects

#

we can convert them to be so, then math on them is easy

#

if you think about it, figuring out what 30 minutes before something is, also takes weird maths

tribal lintel
karmic sparrow
#

if you do this

#
from time import sleep
...
sleep(1)
#

in some other people's code, sleep( means something else

#
from asyncio import sleep
await sleep(1)
#

that is a different sleep

#

datetime is always datetime so there's never any confusion

#

anyway it doesn't matter; just saying that import time is normal and fine

#
from datetime import datetime
import time
#

this is normal and common is what I'm saying ^

tribal lintel
#

mhm thas what i did

#

ty for being patient

karmic sparrow
#

it's all goods

#

ok so now we have the first check

#

in order to do math on this though, we do want the timedelta

tribal lintel
#

imported it

karmic sparrow
#
from datetime import datetime, timedelta
import time
#

ok

#

after we figured out how many hours and minutes we have left,

#

we want to make a new datetime object representing that

#
ring_time = current + timedelta(hours=hours_till_ring, minutes=minutes_till_ring)
#

that means, make a new datetime, with the value of right now, plus that many hours and that many minutes

#

does that make sense

tribal lintel
#

1 sec

karmic sparrow
#

it hasn't done anything for us yet, it's just a datetime thing that is the value of right now + that amount of time

tribal lintel
#

i wanna read for a sec timedelta documentation

karmic sparrow
#

delta means difference

#

it means, do math on a datetime object

#

datetime.datetime.now() + timedelta(hours=3)

#

that returns a new datetime, of whatever time it is in three hours

tribal lintel
#

yes that ik

#

the greek delta, greeks ruining everything

karmic sparrow
#

except salads

tribal lintel
#

or fish

#

as a greek i can say we make excellent fish

#

so basically ring_time is datetime.now() plus how many hours and minutes till ring?

karmic sparrow
#

yeah

tribal lintel
#

ah ok chill

karmic sparrow
#

ok so now the issue is

#

if it's right now 20:24:52:12

#

(seconds and milliseconds)

#

we don't want the alarm to go off at those seconds and milliseconds

tribal lintel
#

so we can strip it

karmic sparrow
#

yeah in a way

#

with datetime we can just replace it with 0

#
ring_time = ring_time.replace(second=0, microsecond=0)
tribal lintel
#

under the first ring_time?

karmic sparrow
#

yeah

#

so now we are telling it

#

add 3 hours, and then just cut off the seconds and microseconds completely

tribal lintel
#

yeah

karmic sparrow
#

so now we want to check if it's exactly 30 minutes beforehand

tribal lintel
#

if hours match we minus minutes of time wanted and current time to check if equals 30

#

or is there simpler way

karmic sparrow
#

timedelta ๐Ÿ™‚

tribal lintel
#

fucking greeks

karmic sparrow
#
while True:
    current = datetime.now()
    if current.hour == hours and current.minute == minutes:
        print('ALARM!')
        break
    elif ring_time - current.replace(second=0,microsecond=0) == timedelta(minutes=30):
        print('warning!')
    time.sleep(5)
#

so here we are ignoring the current second and microseconds (because our loop has a sleep in it, we don't want to not warn just because it's 29.99999999 minutes away)

#

then we are asking, is the ring time minus right now (ignoring s and ms), 30 minutes? if so, print warning

tribal lintel
#

yeah

karmic sparrow
#

but now the issue is, it will loop every 5 seconds

#

and so every 5 seconds for an entire minute it will warn us

#

probably we just want the warning once

#

so we can just store in variable if it was already warned

#

and that's pretty much it

#
import time
from datetime import datetime, timedelta

hours = 0
minutes = 0
while True:
    time_wanted = input("Give me the time you want in a 24 hour format (such as xx:xx): ")
    try:
        hours, minutes = time_wanted.split(':')
        hours = int(hours)
        minutes = int(minutes)
    except ValueError:
        print('I said 24 hour format (such as xx:xx) ...')
        continue

    if not (0 <= hours < 24 and 0 <= minutes < 60):
        print('0-23 hours and 0-59 minutes please!')
        continue
    break

current = datetime.now()
temp_hours = hours
if minutes < current.minute:
    minutes_till_ring = (60 - current.minute) + minutes
    temp_hours -= 1
else:
    minutes_till_ring = minutes - current.minute

if temp_hours < current.hour:
    hours_till_ring = (24 - current.hour) + temp_hours
else:
    hours_till_ring = temp_hours - current.hour

ring_time = current + timedelta(hours=hours_till_ring, minutes=minutes_till_ring)
ring_time = ring_time.replace(second=0, microsecond=0)

print('now', current)
print('wait hours', hours_till_ring)
print('wait minutes', minutes_till_ring)
print(ring_time)

if hours_till_ring == 0:
    print(f"Your timer will ring in {minutes_till_ring} minute(s)")
elif hours_till_ring != 0:
    print(f"Your timer will ring in {hours_till_ring} hour(s)")
warned = False
while True:
    current = datetime.now()
    if current.hour == hours and current.minute == minutes:
        print('ALARM!')
        break
    elif not warned and ring_time - current.replace(second=0,microsecond=0) == timedelta(
            minutes=30):
        print('warning!')
        warned = True
    time.sleep(5)

print('bye!')
tribal lintel
#

my 2d game was less complicated than that damn

#

given it has a bunch of flaws

karmic sparrow
#

time math is a bunch of dumbness normally

tribal lintel
#

math is not fun

#

oh its done right?

#

ill make it send notifications

#

ty for the help, u a real one g

karmic sparrow
#

np

gray scrollBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.

#

๐Ÿ”’ i made this timer of sorts that sends notifcations, and it asks for input twice and idk why