Use multiple values for a variable inside a function - python

I have the following function (which comes from blinkstick library):
bstick.set_color(channel=0, index=0, name="red")
It basically switches on the first led (index=0) in a led strip connected via USB to my computer. index=1 would switch on the 2nd one and so on.
I would want the index parameter to store multiple values from 0 all the way up to 31 (since there are 32 leds in the strip).
I know that an easy and lazy workaround would be to just write the function 32 times and changing the index manually, but is there a smarter way to store 0-31 value inside this?
I tried:
while x < 32:
bstick.set_color(channel=0, index=x, name="white")
x+=1
but this is not really what I want since this is not very friendly with the way the rest of my project has been written so far, which is the following:
from datetime import datetime, time
import pandas
import ctypes
from playsound import playsound
from blinkstick import blinkstick
bstick = blinkstick.find_first()
def bstick_turn_on():
x=0
while x < 32:
bstick.set_color(channel=0, index=x, name="white")
x+=1
def bstick_turn_off():
x=0
while x < 32:
bstick.set_color(channel=0, index=x)
x+=1
file_path = "myfile.xlsx" #sunrise/sunset file path
data = pandas.read_excel(file_path, header=0) #Header on line 0
#Today as day number in reference to 1st of Jan
day = datetime.now().timetuple().tm_yday
#Today's parameters
#sr and ss are column names in the Excel spreadsheet for sunrise and sunset respectively
#Minus 1 to account for 0 based indexing
sunrise = data["sr"][day - 1]
sunset = data["ss"][day - 1]
#Time right now
now = datetime.now().time()
#Function to convert time objects into integers
def seconds_in_time(time_value: time):
return (time_value.hour * 60 + time_value.minute) * 60 + time_value.second
#Variable for a moment in time 5 minutes before the sunset
sunset_minus_five = seconds_in_time(sunset) - 60 * 5
#Setting up the day_night variable depending on the now variable
#delta calculates the difference in seconds between now and sunset -during night- and sunrise -during day-
#A negative value for delta means that now variable is equal to any moment between midnight and the sunrise
if now > sunrise and now < sunset:
day_night = 'day'
delta = (seconds_in_time(now) - seconds_in_time(sunrise))
else:
day_night = 'night'
delta = (seconds_in_time(now) - seconds_in_time(sunset))
#delta_notification calculates the difference in seconds between now and sunset_minus_five
delta_notification = seconds_in_time(now) - sunset_minus_five
#The path to the wallpapers being used
path = 'C:\\Users\\mariu\\Desktop\\Sunset\\wallpapers\\'+ day_night +'.jpg'
#Function defined to perform an action (open/close the light) depending on the time of the day
def on_off():
if now > sunrise and now < sunset:
return bstick_turn_on()
else:
return bstick_turn_off()
#Function to change the wallpaper
def changeBG(path):
ctypes.windll.user32.SystemParametersInfoW(20, 0, path, 3) #SystemParametersInfoW for x64 architecture
#An alarm sound is played and a red light turns on if delta_notification is less or equal than 15 seconds AND delta_notification is greater than -30 delta_notification <= 15 and delta_notification => -30:
if delta_notification <= 15 and delta_notification >= -30:
playsound('alarm.wav') #Plays the sound
bstick_turn_on()
#Wallpaper changes, a three-beep sound is played, and light turns on only if delta is less than 60 seconds AND delta is greater than -1
#In order for the light to turn on, the script should be ran on a computer that is on the same network as the light bulb (wireless)
if delta <= 15 and delta >= -30:
changeBG(path)
playsound('sound.mp3') #Plays the sound
on_off()

Since it appears all 32 lights are turned on or off together, I'd recommend making a function with parameters.
def set_light(color=None, count=32):
args = {'channel': 0}
if color is not None:
args['name'] = color
for x in range(count):
bstick.set_color(**args, index=x)
To turn things off, set_light(), to turn things on, set_light('white').

Related

An accurate stop watch using Python for logging minutes and hours worked. What's the best way to go about it? [duplicate]

This question already has answers here:
How to increase sleep/pause timing accuracy in python?
(4 answers)
Closed 5 months ago.
I've tried a few solutions from here with no luck. My Python timers are 10-30 seconds behind my smartphone stop watch after 10 minutes. I've tried the following:
def background3():
while True:
second = 0
minute = 0
hours = 0
while(True):
print('%d : %d : %d'%(hours,minute,second))
time.sleep(1)
second+=1
if(second == 60):
second = 0
minute+=1
if(minute == 60):
minute = 0
hour+=1;
and I also tried this:
def showCounter(self):
# Check the value of startWatch variable to start or stop the Stop Watch
if self.startWatch:
# Increment counter by 1
self.counter += 1
# Count and set the time counter value
cnt = int((self.counter/10 - int(self.counter/10))*10)
self.count = '0' + str(cnt)
# Set the second value
if int(self.counter/10) < 10 :
self.second = '0' + str(int(self.counter / 10))
else:
self.second = str(int(self.counter / 10))
# Set the minute value
if self.counter / 10 == 60.0 :
self.second == '00'
self.counter = 0
min = int(self.minute) + 1
if min < 10 :
self.minute = '0' + str(min)
else:
self.minute = str(min)
# Merge the mintue, second and count values
text = self.minute + ':' + self.second
# Display the stop watch values in the label
self.label.setText('<h1 style="color:white">' + text + '</h1>')
I'd like to be able to update a pyqt5 qlabel as time goes by every second, and I'd like to be able to display hours, minutes, and seconds in the qlabel. This has to be accurate as it is for work logging purposes. Eventually, I want to implement a qlabel that takes my overtime rate into consideration, and updates $ earned as time goes by. Does anybody have an example of what this may look like in pyqt5 using perhaps OS time ? Or is there some better way to do this?
EDIT:
This question is not a duplicate. The suggested articles were not helpful. I essentially need a way to count up from 0 using datetime. I tried replacing datetime.now but that did not work. The solutions suggested do not update my value in real time. They just take a stamp at the beginning, and subtract it from the end time. this is not what I am looking for. Does anybody know how I can watch seconds, minutes, and hours go by in real time through a pyqt5 qlabel?
def showCounter(self):
if self.startWatch:
text = str(datetime.now().strftime("%H:%M:%S"))
self.label.setText('<h1 style="color:white">' + str(text) + '</h1>')
Here's some code that prints every passing second without accumulating any lag. Just check the built-in clock at least once per second and update if the second has changed.
from datetime import datetime
import time
def time_to_str(time):
return str(time.hour) + ':' + str(time.minute) + ':' + str(time.second)
cur_time = datetime.now()
cur_str = time_to_str(cur_time)
while True:
time.sleep(0.2) # 200 ms, arbitrary
new_time = datetime.now()
new_str = time_to_str(new_time)
if new_str != cur_str:
print(new_str)
cur_str = new_str
The more often you check the time, the faster you can respond to the start of a new second. You'll never accrue lag regardless because you only print the time immediately after getting it from the system.
You should not expect a manufactured timer that relies on sleep() to be accurate for accrued time (stopwatch). Even if sleep() were 100% accurate, you are losing time outside of that in all of the function calls and other parts of the loop, which adds up over time (pun intended.)
The system time should be used. You can either use:
time.time()
or
datetime.now()
both have methods to peel out H:M:S.
As far as your "update loop"... well that is another story, you could use sleep there or whatever PyQt has to offer to refresh, but when you need to pull the time, do it as above.
If you want to use either as a "stopwatch" just capture the start time, do the subtraction. If you do this with datetime objects, the delta is a timedelta object that you can query. Do a little googling on timedelta and datetime.
Example:
In [1]: from datetime import datetime, timedelta
In [2]: tic = datetime.now()
In [3]: toc = datetime.now()
In [4]: td = toc - tic
In [5]: type(td)
Out[5]: datetime.timedelta
In [6]: td.seconds
Out[6]: 8

Simple python script using 100% CPU on rPi3B+

I have raspberry pi model 3b+ with a HC-SR04 ultrasonic distance sensor (there is also a couple of ds18b20 and a DHT21 but I think they're unrelated to my problem).
I have found a python script to make measurements from it and modified it to my needs - mostly to take a couple of reading spanned in time, take an average from it and map the value to range from 0 to 100, as the percentage and commit it to the influx database for grafana and domoticz.
The code:
#source: https://tutorials-raspberrypi.com/raspberry-pi-ultrasonic-sensor-hc-sr04/
#Libraries
import RPi.GPIO as GPIO
import time
from influxdb import InfluxDBClient
import sys
# https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Python
import requests
client = InfluxDBClient(database='pellet')
series = []
#GPIO Mode (BOARD / BCM)
GPIO.setmode(GPIO.BCM)
#set GPIO Pins
GPIO_TRIGGER = 23
GPIO_ECHO = 22
#set GPIO direction (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def distance():
# set Trigger to HIGH
GPIO.output(GPIO_TRIGGER, True)
# set Trigger after 0.01ms to LOW
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
StartTime = time.time()
StopTime = time.time()
# save StartTime
while GPIO.input(GPIO_ECHO) == 0:
StartTime = time.time()
# save time of arrival
while GPIO.input(GPIO_ECHO) == 1:
StopTime = time.time()
# time difference between start and arrival
TimeElapsed = StopTime - StartTime
# multiply with the sonic speed (34300 cm/s)
# and divide by 2, because there and back
distance = (TimeElapsed * 34300) / 2
return distance
def pellet(dist):
# zmierzona odleglosc
# dist = distance()
# do zmierzenia poziom maksymalny
# 63 - do pokrywy
in_min = 63
# do zmierzenia poziom minimalny
in_max = in_min + 100
#wyjscie jako procent, od 0 do 100
out_min = 100
out_max = 0
# map z arduino: https://www.arduino.cc/reference/en/language/functions/math/map/
return (dist - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
def loop():
# nie wiecej jak 200 iteracji
loop = 200
# suma
total = 0
# tabelka z pojedynczmi wynikami
measurements = []
# liczba pomiarow do zrobienia
counter = 10
counter1 = 0
# czas pomiedzy pomiarami
sleep =30
#
while loop > 0:
loop -= 1
time.sleep(sleep)
# koniec, jesli wykonano liczbe pomiarow
if counter == 0:
#print(total/10)
return pellet(total/10), measurements
break
if loop == 0 and counter1 != 0:
return pellet(total/counter1), measurements
break
if loop == 0 and (counter1 == 0 or total == 0):
GPIO.cleanup()
sys.exit()
dist = distance()
# jesli wynik jest zly
if dist < 63 or dist > 163:
print("nie ok")
continue
counter -= 1
measurements.append(dist)
counter1 += 1
total += dist
print("total po ",counter1 , "sek: ", total, "dist: ", dist)
print(total/10)
#return total/10
if __name__ == '__main__':
try:
#dist = distance()
#print ("Measured Distance = %.1f cm" % dist)
#print (pellet(dist))
loop=loop()
print("avg :", loop[0])
#print("measurs :", loop[1])
#print("test :", loop[1][2])
if (1):
point = {
"measurement": "pellet",
"tags": {
"location": "piwnica",
"type": "hc-sr04"
},
"fields": {
"value": loop[0],
"raw_measurement1": loop[1][0],
"raw_measurement2": loop[1][1],
"raw_measurement3": loop[1][2],
"raw_measurement4": loop[1][3],
"raw_measurement5": loop[1][4],
"raw_measurement6": loop[1][5],
"raw_measurement7": loop[1][6],
"raw_measurement8": loop[1][7],
"raw_measurement9": loop[1][8],
"raw_measurement10": loop[1][9]
}
}
series.append(point)
client.write_points(series)
url = 'http://localhost:8080/json.htm?type=command&param=udevice&nvalue=0&idx=13&svalue='+str(loop[0])
r = requests.get(url)
GPIO.cleanup()
# Reset by pressing CTRL + C
except KeyboardInterrupt:
print("Measurement stopped by User")
GPIO.cleanup()
The problem is I noticed that the CPU temperature graph was elevated, with many short valleys to the about correct temperature.
When I ssh'd to the pi and run htop I saw that it was this script that is using 100% cpu.
But the weirdest thing is that the script is running in crontab every 15 minutes since yesterday, from about 14:30 and raise CPU temp started today at around 11:00.
I'm not a developer or a programmer and I just mostly copied the code from around the web so I don't know if this is some part of the code that did this (but why after 21 hours?) or what and why, and how to debug and fix it.
so it isn't just enviromental thing as the pi is in the attic where is about 5C to 10C.
Thank you for your help.
Here:
while GPIO.input(GPIO_ECHO) == 0:
StartTime = time.time()
this says "if the pin is 0, save the time, if the pin is zero, save the time, if the pin...." incessantly. You'll want to wait a little time after each check
while GPIO.input(GPIO_ECHO) == 0:
time.sleep(0.001) # 1 ms
StartTime = time.time()
The check itself probably takes ~us, so this will reduce CPU usage by 99%. You might want to do the same for the pin==1 case, depending on how accurate you need the times to be.
While it is impossible to know for sure where the issue lies without debugging directly on your system, and a glance at the code reveals several possible bugs in the logic, the one place that is most likely to cause the issue is the distance function.
As #mdurant already pointed out, your read loops will jump the CPU usage to 100%, but I suspect there is also another issue:
The trigger code and the read code are time sensitive!
The problem is, we don't know how much time actually passes between
# set Trigger to HIGH
GPIO.output(GPIO_TRIGGER, True)
# set Trigger after 0.01ms to LOW
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
and:
# save StartTime
while GPIO.input(GPIO_ECHO) == 0:
StartTime = time.time()
# save time of arrival
while GPIO.input(GPIO_ECHO) == 1:
StopTime = time.time()
While this simple algorithm - pulse trigger, count return interval will work on a microcontroller like Arduino, it is not reliable on a full blown computer like Raspberry Pi.
Microcontrollers run a single thread, with no OS or task scheduling, so they run code in real time or as close to it as possible (borrowing a few interrupts here and there).
But in your case you are running an interpreted language on a multitasking operating system, without explicitly giving it any high priority.
This means, your process could be suspended just enough time to miss the return "ping" and get stuck in the first loop.
This may only happen rarely when something else puts a load on the Pi, which would explain why you only noticed the issue after 21 hours running.
You should implement some form of timeout for GPIO reading loops and return an error value from the distance function if that timeout is reached to ensure you do not have an infinite loop when something goes wrong with the hardware, or you miss the return ping due to scheduling issues.
I suggest something like this:
def distance():
MAX_READ_ATTEMPTS = 10000 #this is a random value I chose. You will need to fine-tune it based on actual hardware performance
# set Trigger to HIGH
GPIO.output(GPIO_TRIGGER, True)
# set Trigger after 0.01ms to LOW
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
# lets not have any unneeded code here, just in case
# save StartTime
while GPIO.input(GPIO_ECHO) == 0 and retry_counter < MAX_READ_ATTEMPTS:
retry_counter += 1
StartTime = time.time()
# maximum number of retries reached, returning with error condition
if retry_counter == MAX_READ_ATTEMPTS:
return -1
reatry_counter = 0
# save time of arrival
while GPIO.input(GPIO_ECHO) == 1 and retry_counter < MAX_READ_ATTEMPTS:
retry_counter += 1
StopTime = time.time()
# maximum number of retries reached, returning with error condition
if retry_counter == MAX_READ_ATTEMPTS:
return -1
# time difference between start and arrival
TimeElapsed = StopTime - StartTime
# multiply with the sonic speed (34300 cm/s)
# and divide by 2, because there and back
distance = (TimeElapsed * 34300) / 2
return distance
I am intentionally not adding a delay between reads, because I am not sure what the tolerance for this measurement is in terms of timing, and sleep functions can't guarantee an exact delay (again, due to OS / CPU scheduling).
A brief 100% CPU load should be worth it to ensure accurate and valid measurements, as long as it is not kept up for too long, which our retry counting method should prevent.
Note that my only experience with ultrasonic sensors is using Arduino where a special pulseIn function is used that takes care of the implementation details of measurement so this solution is mostly an educated guess and I have no way of testing it.

Python send email when sensor has certain water level

I am developing an application on a raspberry pi with an HC-SR01 sensor. For now I have a python script that checks the water level every second.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO_TRIGGER = 16
GPIO_ECHO = 18
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def distance():
# set Trigger High
GPIO.output(GPIO_TRIGGER, True)
# set Trigger after 0.1ms low
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
startTime = time.time()
endTime = time.time()
# store start time
while GPIO.input(GPIO_ECHO) == 0:
startTime = time.time()
# store arrival
while GPIO.input(GPIO_ECHO) == 1:
endTime = time.time()
# elapsed time
TimeElapsed = endTime - startTime
# multiply with speed of sound (34300 cm/s)
# and division by two
distance = (TimeElapsed * 34300) / 2
return distance
while True:
dist = distance()
print ("Entfernung = %.1f cm" % dist)
time.sleep(1)
This is working fine and now I want to send an E-Mail to myself then the water level is above a certain limit. The sending of the E-Mail is not the problem but the logic when to send it.
If I put a sendEmail() function in the while loop I would get an E-Mail every second when the water level is reached. So the following wouldn't do it:
#global varaible
alarm_waterlevel = 170
#in while loop
if dist > alarm_waterlevel
sendMail()
So I'm looking for a clever solution to only send the mail once the water level is reached.
I was thinking about a global variable and check if the water level has dropped below a certain point before triggering the mail again. Something like this:
#global varaible
alarm_waterlevel = 170
mail_sent = false
#in while loop
if dist >= alarm_waterlevel && mail_sent == false
sendMail()
mail_sent = true
if dist <= alarm_waterlevel - 10
mail_sent = false
Do you think this is a fault tolerant solution? Any good advices out there to help me get around with this?
Your approach looks reasonable to me, for a Raspberry Pi solution ;)
Another thing that you could think of is adding maybe three different warning levels or states that your system can be in.
L1: send once, 80% full
L2: send every 5 minutes, 90 % full
L3: send every minute, > 100 %
And you have to think of when to change the states. You could add something like a hysteresis. That could be elegant so you don't have to use three different height levels.
If the water level increases you could switch the state, e.g. at 80 % but only switch back to a lower warning state when it is below 70 %. The idea is that your system is not constantly changing states when the water level is between 78 % and 82 %.
Another thing that you could think of is like a projection by looking at the derivative (first or maybe additionally second) of the water level. Then you could warn even earlier when the water level is rising quickly but it is still below a critical threshold.
I think you have a general logic problem in your if statement.
You want to send an e-mail when the distance is greater than or equal to your alert level.
I think your ultrasonic sensor measures from top to bottom, so your if statement should be:
size_water_container = 200 #Just a estimadet value
if dist < (size_water_container - alarm_waterlevel) and waterlevel_before > (size_water_container - alarm_waterlevel):
sendMail()
If i am wrong, than ignore it :)
But now to your Question.
If you permanently query the distance, than you have to permanently save your waterlevel_before, but not in the if statement. Just do it afterwards
alarm_waterlevel = 170
size_water_container = 200
waterlevel_before = 0
while True:
dist = distance()
if dist < (size_water_container - alarm_waterlevel) and waterlevel_before > (size_water_container - alarm_waterlevel):
sendMail()
waterlevel_before = dist
time.sleep(1)

Knowing if time has already passed or not python

Im using this code right now to get the difference of two different times
from time import strftime
from datetime import datetime
fmt = '%H:%M'
currentTimeString = strftime(fmt) #get the current time
gameTimeObject = datetime.strptime(time , fmt)
currentTimeObject = datetime.strptime(currentTimeString, fmt)
diff = currentTimeObject-gameTimeObject
diff_minutes = diff.seconds/60
I have a for loop that loops through different time values, 11:00, 12:00, 13:00, 14:00.
For the purpose of this example lets say the currentTime is 13:23
Im getting the result that i want when the time has passed meaning, 11:00, 12:00, 13:00 but when it comes to 14:00 the diff_minutes shows the value 1403
Why this is a problem is because I'm doing this after that code is executed
if diff_minutes >= 0 and diff_minutes <= 47:
time = str(diff_minutes)
elif diff_minutes >= 48 and diff_minutes <= 58:
time = "HT"
elif diff_minutes >= 59 and diff_minutes <= 103:
time = str(diff_minutes)
elif diff_minutes >= 104 and diff_minutes <= 107:
time = "90'"
elif diff_minutes >= 108: # HERE IS THE PROBLEM <<<<<<-------
time = "FT"
As you can see the times that has not yet been passed will change to "FT" since I'm using that if statement to know if the time of a games is over. How can i fix this?
--- EDIT more information of what I'm trying to do as asked
So what I'm trying to do here is to set the time variable to a soccer game. The different times as mentioned above 13:00 etc are the times of which when the game starts. So what i want to do is if the currentTime is 13:23, then i would change the time label of that soccer game to 23' since 23minutes has passed. If the total time that has passed is over 108 minutes then it means the game is over that is why i set the time variable to "FT" in the last if statement.
As i said before this is where the problem occurs since the diff_minutes gives me a value of higher than 108 minutes when the games has not yet been started it will change the time variable to "FT" which is wrong
So what we really should do is work only with datetime objects here. When you do math on them, the produce timedelta objects. These timedelta objects are comparable. This makes writing your code secretarial. Also - since an if/elif/else tree is short circuiting, you need not check if a time is between two times, just less than the upper bound. I admit my domain knowledge of soccer is limited to knowing it is a 90 minute game, so you may need to adjust this, but it should give you the idea.
import datetime
def gametime(hour, minute):
now = datetime.datetime.now()
starttime = datetime.datetime.combine(datetime.date.today(), datetime.time(hour, minute))
dif = now - starttime
if dif < datetime.timedelta(seconds=48*60):
return dif.seconds / 60
elif dif < datetime.timedelta(seconds=58*60):
return "Half Time"
elif dif < datetime.timedelta(seconds=104*60):
return dif.seconds / 60
elif dif < datetime.timedelta(seconds=108*60):
return "90'"
else:
return "Final"
PS: Seriously, Guido?
PPS: I should have tested this before posting it. I am sorry that I did not.

24-Hour Time Conversion to 12-Hour Clock (ProblemSetQuestion) on Python

I am a beginner programmer in Python and I have no idea how to proceed with the following question. There are a ton of similar questions out there, however there are none having to do with Python code.
I have tried to compare the strings but I am uncertain how to make the comparison. I'm pretty sure I need to take the first two numbers (hours) and divide by 12 if it is greater than 12 ... but that presents problems.
Question:
Time Conversion (24hrs to 12hr)
Write a function that will allow the
user to convert the 24 hour time format to the 12 hour format (with
'am','pm' attached). Example: from '1400' to '2:00pm'. All strings
passed in as a parameter will have the length of 4 and will only
contain numbers.
Examples (tests/calls):
>>> convertTime('0000')
'12:00am'
>>> convertTime('1337')
'1:37pm'
>>> convertTime('0429')
'4:29am'
>>> convertTime('2359')
'11:59pm'
>>> convertTime('1111')
'11:11am'
Any input or different methods would be awesome!
You could use the datetime module, but then you would have to deal with dates as well (you can insert wathever you want there). Probably easier to simply parse it.
Update: As #JonClements pointed out in the comments to the original question, it can be done with a one liner:
from datetime import datetime
def convertTime(s):
print datetime.strptime(s, '%H%M').strftime('%I:%M%p').lower()
You can split the input string in the hours and minutes parts in the following way:
hours = input[0:2]
minutes = input[2:4]
And then parse the values to obtain an integer:
hours = int(hours)
minutes = int(minutes)
Or, to do it in a more pythonic way:
hours, minutes = int(input[0:2]), int(input[2:4])
Then you have to decide if the time is in the morning (hours between 0 and 11) or in the afternoon (hours between 12 and 23). Also remember to treat the special case for hours==0:
if hours > 12:
afternoon = True
hours -= 12
else:
afternoon = False
if hours == 0:
# Special case
hours = 12
Now you got everything you need and what's left is to format and print the result:
print '{hours}:{minutes:02d}{postfix}'.format(
hours=hours,
minutes=minutes,
postfix='pm' if afternoon else 'am'
)
Wrap it up in a function, take some shortcuts, and you're left with the following result:
def convertTime(input):
h, m = int(input[0:2]), int(input[2:4])
postfix = 'am'
if h > 12:
postfix = 'pm'
h -= 12
print '{}:{:02d}{}'.format(h or 12, m, postfix)
convertTime('0000')
convertTime('1337')
convertTime('0429')
convertTime('2359')
convertTime('1111')
Results in:
12:00am
1:37pm
4:29am
11:59pm
11:11am
Some tips
int("2300") returns an integer 2300
2300 is PM.
time >= 1200 is PM
time between 0000 and 1200 is AM.
You could make a function that takes a string, evaluates it as integer, then checks if it is greater or less than the above conditions and returns a print.
import datetime
hour = datetime.datetime.now().strftime("%H")
minute = datetime.datetime.now().strftime("%M")
if int(hour) > 12:
hour = int(hour) - 12
amPm = 'PM'
else:
amPm = 'AM'
if int(hour) == 12:
amPm = 'PM'
if int(hour) == 0:
hour = 12
amPm = 'AM'
strTime = str(hour) + ":" + minute + " " + amPm
print(strTime)
Take hour and minute from datetime. Convert hour to an int. Check if int(hour) > 12. If so, change from AM to PM. Assign hour with int(hour) - 12. Check if hour is 0 for 12 AM exception. Check if hour is 12 for 12 PM exception. Convert hour back into a string. Print time.

Categories