24 hour time into 12 hour time - python

I need to make a simple program which converts a 24 hour time which is input, into 12 hour time, which produces an error if an incorrect time is put in. I currently have the code below, however, I have a few issues. One issue is that if "0924" is input, it outputs "924 am", when I need it to produce "9:24am" (the space isn't hugely important but it's preferred). Also, I'm not entirely sure where to start for doing 0001-0059, because "0001" for example produces "1 am", which is obviously incorrect.
print("Enter a time in 24 hour time, e.g. '1620'")
time = (int(input("Time: ")))
normal = 0
if (time == 0000):
normal="12:00am"
print (normal)
elif (time>1200):
normal = (time - 1200)
print (int(normal), ("pm"))
elif (time<1200):
normal = time
print (int(normal), ("am"))
Thanks in advance for any help!

Try this
import time
timevalue_24hour = "1620";
timevalue_24hour = timevalue_24hour[:2] + ':' + timevalue_24hour[2:]
print (timevalue_24hour)
t = time.strptime(timevalue_24hour, "%H:%M")
timevalue_12hour = time.strftime( "%I:%M %p", t )
print (timevalue_12hour)
Take input as a string. Assign it to timevalue_24hour and rest will work

When printing, normal is just a number. The 0s disappear because you don't write 0s in front of numbers normally. I would suggest doing something like this
def normal_check(num):
if num < 10:
return "000"+str(num)
elif num < 100:
return "00"+str(num)
elif num < 1000:
return "0"+str(num)
else:
return str(num)
print("Enter a time in 24 hour time, e.g. '1620'")
time = (int(input("Time: ")))
normal = 0
if (time == 0000):
normal="12:00am"
print (normal)
elif (time>1200):
normal = normal_check(time - 1200)
print (normal, ("pm"))
elif (time<1200):
normal = normal_check(time)
print (normal, ("am"))

The best way to do this will be to take the input as an str rather than int. Take it in as str and split it into two int values of two digits.
Then the first string if less than 12 will be hour else subtract 12 from first str and use PM. Also, the second str will just be minutes.

Related

How can I utilize OOP with this basic calculation script?

I am trying to write a simple calculator to calculate how fast my battery will drain from 100% to 0% by taking a time and percentage for start and subtracting it from the finish time and percentage.
I was able to make a quick and dirty script to accomplish this, but I am learning OOP, and I would like some feedback on how to improve my code and implement OOP for this task. I added in some verbose print statements to make it easier for me to remember what everything is when I run it, and I intend to wrap it up into a simple bash script or maybe implement tkinter for GUI.
Any thoughts or suggestions will help! My main environment is python 3, but I added the error handling for those who run with python2 because it doesn't like a preceding 0 in the time number.
from datetime import timedelta
# Getting inputs for time and percentage
try:
start_time = str(input('What is the starting time in 24 hour time? Format: HHMM >> '))
start_time_hr = start_time[:2]
start_time_min = start_time[2:]
except SyntaxError:
print('Try entering the time again without the preceding 0. \n')
start_time = str(input('What is the starting time in 24 hour time? Format: HHMM >> '))
start_time_hr = start_time[0]
start_time_min = start_time[1:]
start_perc = int(input('What is the starting battery percentage? >> '))
try:
end_time = str(input('What is the finish time in 24 hour time? Format: HHMM >> '))
end_time_hr = end_time[:2]
end_time_min = end_time[2:]
except SyntaxError:
print('Try entering the time again without the preceding 0. \n')
end_time = str(input('What is the finish time in 24 hour time? Format: HHMM >> '))
end_time_hr = end_time[0]
end_time_min = end_time[1:]
end_perc = int(input('What is the ending battery percentage? >> '))
# Turning numbers into times for calculation
start = timedelta(hours=int(start_time_hr), minutes=int(start_time_min))
end = timedelta(hours=int(end_time_hr), minutes=int(end_time_min))
# Calculating and printing the results
perc_difference = float(-(end_perc - start_perc))
time_difference = end - start
time_difference_minute = time_difference.total_seconds() / 60
discharge = (100.0 * time_difference_minute / perc_difference) / 60
print()
print()
print('*****')
print('Percentage Difference = ' + str(perc_difference))
print('Minutes Passed = ' + str(time_difference.total_seconds() / 60))
print('100% to 0% in ~' + str(round(discharge, 2)) + ' hours.')
print('*****')
print()
print()
print()
I don't think this program will benefit from using OOP.
That said; I do have a few notes on style and lack of defensive programming.
First; You do not need to wrap an input call with str, since it returns a string by default.
Second; You have wrapped a couple of your input calls with int, which is perfectly fine, but these need to be wrapped in try blocks as any input that cannot be converted to an integer will raise a ValueError.
Third; You should NEVER be handling a syntax error in that way. If you're getting syntax errors, fix the code, don't try to wrap it with a bandaid.
Fourth; You do not need to write that many print statements.
The entire print block could be rewritten as follows:
print('*****\nPercentage Difference = ' + str(perc_difference) + 'Minutes Passed = ' + str(time_difference.total_seconds() / 60)) + "\n100% to 0% in ~' + str(round(discharge, 2)) + ' hours.\n' +
*****')
Or, in my opinion; the much more readable fstring variant:
msg = f"*****\nPercentage Difference = {perc_difference}\nMinutes Passed = {time_difference.total_seconds() / 60}\n100% to 0% in ~{round(discharge,2)} hours.\n"
print( msg )

Time conversion to a path file

I have a path files which are named by time (201803061500) etc. What I need is a time conversion, because I use while loop to open a few of them there is an error when I want files from for example (...1555 to ... 1615) and Python sees an obivous problem because after 1555 is 1560, but I want him to convert that to time so after (...1555 will be ... 1600) any ideas how to use it?
Btw. Time conversion must be contain 4 digits, so it cannot be 16:00/16-00 etc. it must be 1600, because it goes as an input to my pathfile. Any ideas?
UPDATE - I did this, but this code is rubbish and I think my problem might be solved by one command.
Start_time_hours = input('Enter start time (hh): ' )
Start_time_minutes = input('Enter start time (mm): ')
if Start_time_hours >= 24:
print ("Values from 00 to 23 only!")
if Start_time_minutes >= 60:
x = Start_time_hours + 1
y = Start_time_minutes - Start_time_minutes
if y == 0:
print "Ok"
print x, y
if Start_time_minutes <= 55:
print Start_time_hours, Start_time_minutes
One easy way to handle unformated time is the datetime. You can first strip your strings and then do whatever you want !
from datetime import datetime, timedelta
from time import strtime
datetime_object = datetime.strptime(file_name, '%Y%m%d%H%M')
print(datetime_object) # returns '2018-03-06 15:00:00'
delta = timedelta(minutes=5)
next_time = datetime_object + delta
print(next_time) # returns '2018-03-06 15:05:00'
Finally you can get your string back by using time.strftime() function
new_string = next_time.strftime('%Y%m%d%H%M')
print(new_string) # returns '201803061505'
Source datetime: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior
Source time: https://docs.python.org/2/library/time.html
Start_time_hours += (Start_time_minutes / 60)
Start_time_minutes %= 60
Start_time_minutes += 5
Those three lines solved my problem, datetime also works, but if you put those variables to input pathfile, you'll get an error. That's why I've choosen this solution.

How to do the correct casting using a loop in python?

The objective is to write a program that will increase the population every 7 and 35 seconds and decrease every 13 seconds. I am trying to use a loop for this program and I am having some problems with getting the right casting for each variable. Here's the code:
#(1)There is a birth every 7 seconds (2)There is a death every 13 seconds (3)There is a new
immigrant every 35 seconds.
#CURRENT POP: 307,357,870
populationCurrent = input("What is the current population")
x=0
while x!=100:
if (x%7==0):
populationCurrent=populationCurrent+1
x=x+1
elif (x%13==0):
populationCurrent=populationCurrent-1
x=x+1
elif (x%35==0):
populationCurrent+=1
x=x+1
else:
x=x+1
print("The population will be "+int(populationCurrent)+".")
Thank you for your time.
I think you are confused in python2 and python3, there's a difference in input() function of python 2.x and python 3.x, where input() function gives an integer value in python 2 and str in python 3
input() is str by default so, this should be converted to int
populationCurrent = str(input("What is the current population"))
You cannot concatenate string and int
print("The population will be "+str(populationCurrent)+".")
Its easier to do this than iterate through 100 times
populationCurrent += 100//7 + 100//35 - 100//13
You need to convert populationCurrent to an integer immediately after you read the string.
populationCurrent = int(input("What is the current population"))
Note that if you don't enter a string that is a valid integer representation, this will raise a ValueError. You might want to consider how to handle that (catch it and use a default value? catch it and try to read another value? Let the exception propagate?)
With this change, you'll have to convert the integer value back to a string for the output:
print("The population will be "+str(populationCurrent)+".")
or using any of the various string formatting tools available. It's better to have populationCurrent as an integer, since there are more places in your code that assume it to be an integer than assume it to be a string.
The only thing you need to do is convert populationCurrent from string to int:
populationCurrent = int(input("What is the current population?"))
The more concerning stuff is that your code doesn't do what it's supposed to: when x is 35 you will only have one birth, since 35 % 7 is 0, but no immigrant will arrive. Do something like this, removing the elif statements which do not make the code that more efficient anyway:
while x!=100:
if (x%7==0):
populationCurrent=populationCurrent+1
if (x%13==0):
populationCurrent=populationCurrent-1
if (x%35==0):
populationCurrent+=1
x=x+1
print("The population will be ", populationCurrent, ".")
Though still note that the loop will stop after x gets to 100. You could reset it but I don't know for how long you want it to run.
def intInput(prompt):
while 1:
try: return int(input(prompt))
except ValueError: print("Invalid Input!")
def YearToModifier(x):
if x%35 ==0 or x%7 ==0: return 1
if x%13 == 0: return -1
return 0
populationCurrent = intInput("What is the current population?") #ensure you get an int
n_years = intInput("How Many Years?") #ensure you get an int
#in this case populationChange is independent of initial population (this is rarely the case in reality)
populationChange = sum(YearToModifier(x) for x in range(n_years))
#the population in the future is the initialPopulation + population Change ... duh...
populationFuture = populationCurrent + populationChange
print("The Population will be %d!"%populationFuture)
there you go
WRT #martjinpeters comment on OP you could change YearToModifier to
def YearToModifier(x):
return sum([x%35 ==0,x%7 ==0,-1*int(x%13 == 0)])
of coarse as #AshokaLella points out you can calculate the total births/immigrations/deaths for a given number of years without actually visiting each year
births = n_years//7
immigrations = n_years//35
deaths = n_years//13
populationChange = births + immigrations - deaths

What is the best way to write a function that converts an integer of minutes into a string formatted in "X hour(s) Y minute(s)"?

I currently have my Django custom template filter like this:
from django import template
register = template.Library()
#register.filter
def duration(value):
hours = value / 60
minutes = value % 60
hours_string = str(hours) + (" hours" if hours > 1 else " hour" ) if hours else ""
minutes_string = str(minutes) + (" minutes" if minutes > 1 else " minute") if minutes else ""
return ' '.join("{hours} {minutes}".format(hours=hours_string, minutes=minutes_string).split())
Some possible outputs:
1 hour 25 minutes
2 hours
45 minutes
3 hours 1 minute
The ' '.join(....split()) trick was something I got from this solution. I realize I only need to check for the extra string at either the beginning or the end of the string (for when it's 0 hours or 0 minutes), but it seems to do the trick and maybe it's easier to read than regular expression to some people.
I also feel that I am violating DRY since I am repeating almost the exact same if-then block twice. I was thinking of something like...
for i, unit in enumerate([hours, minutes]):
# Do some code.
return ' '.join("{hours} {minutes}".format(hours=value[0], minutes=value[1]).split())
but I couldn't figure out how to choose between "hour(s)" or "minute(s)" without another if-then block. Also the two short-hand if-then per line also looks a bit ugly too...
I'll appreciate any suggestions or tips. Thanks!
import datetime
def pprint(val):
if val == 1:
return '1 minute'
x = str(datetime.timedelta(minutes=val))[:-3].split(':')
r = ''
if int(x[0]):
r += x[0]+' hours' if int(x[0]) > 1 else x[0]+' hour'
if int(x[1]):
r += ' %s minutes' % int(x[1]) if int(x[1]) > 1 else ' %s minute' % int(x[0])
return r.strip()
Sample run:
>>> pprint(65)
'1 hour 5 minutes'
>>> pprint(1)
'1 minute'
>>> pprint(60)
'1 hour'
>>> pprint(61)
'1 hour 1 minute'
You can easily expand this to include days as well, but since you specifically mentioned only hours and minutes I adjusted the method.
The main heavy lifting is done by datetime.timedelta, the rest is just string parsing.
I use this for modular unit conversions, including the sort you've described. I wrote it while working for UCI, and UCI gave permission to distribute it under a specific opensource license:
http://stromberg.dnsalias.org/~strombrg/modunits/
You can use it as a shell-callable for POSIX shell scripts, or it can be used as a python module via import.
I consider it production-quality, and indeed use it in a production role (backups) regularly.
This is my very first attempt at Python, so if this is totally missing your actual goal or is wrought with errors, lemme know and I'll delete.
To keep things DRY, and to eliminate the output of "0 hours" or "1 minutes", this should work, so long as we accept the premise that the base unit (in this case minute and hour) can be pluralized by simply adding an 's'. Anything more complex and you'll want a python ninja:
def format_output(value, unit):
if value == 0:
return ""
singular_output = str(value) + " " + unit
if value == 1:
return singular_output
elif value > 1:
return singular_output + "s"
def duration(value):
hours = value // 60
minutes = value % 60
formatted_string = format_output(hours, "hour") + " " + format_output(minutes, "minute")
return formatted_string.strip()
The one condition the above does not account for is if duration is 0 or blank, which I think should return "0 minutes", but that is an easy fix that is best left to your needs.
Also, I added in the strip() method, otherwise you'll be left with leading or trailing space if one of the two units comes out to zero.

String formatting %02d not performing as expected? What would cause the following code to not print truncated two-digit form?

No clue why this is happening. I must be missing something obvious.
I'm trying to make a counter print out something like SMPTE code (hours:minutes:seconds:frames (assuming 24fps)).
Code thus far:
import time
s_time = time.time()
def format_time():
t = time.time() - s_time
if t < 1:
print '00:00:00:%02d' % int(t/0.041666666666666664)
elif t < 60:
t = str(t).split('.')
print '00:00:%02d:%02d' % (int(t[0]), int(int(t[1][:4])/0.041666666666666664) )
while True:
format_time()
All seems well initially, until the duration surpasses 1 second and the elif branch is entered. Seconds print out fine, but the frames print out the full multi-digit result of the calculation. Given that the formatting operator is specifying %02d, just like it does in the first if branch (which behaves as expected), why is it not obeying in the second branch? I'm at a loss trying to figure out why it is still printing the full result rather than the truncated version.
You are trying to get the integer part and the fractional part of the float to print your result. It is a good practice to use operators and functions on numeric data directly instead of adding a heavy overhead by converting the float into str and back to number.
Use the math module modf function for that. It will also simplify your algorithm.
import time
import math
s_time = time.time()
def format_time():
t = time.time() - s_time
if t < 60:
f,i = math.modf(t)
print '00:00:%02d:%02d' % (i, f/0.041666666666666664)
while True:
format_time()
PS: for your code error, in your elif block, you are passing t as an integer with a huge value instead of passing the 0.xxxxx value of it. This error wouldn't occur if you keep using the math functions of floats.
I expect you want something like this:
hours = int(t)/3600
minutes = (int(t)/60)%60
seconds = int(t)%60
frames = (t-int(t))*24
print '%02d:%02d:%02d:%02d' % (hours, minutes, seconds, frames)
%02d means: print the integer and if it's shorter than 2 digits, prefix it with zeroes.
it doesn't limit the formatted string to two digits.
edit: one way of getting the first 2 (rounded) digits of a number n would be:
n = 13900
print round(n/10**math.floor(math.log10(n)-1))
or if you don't care about rounding, just cut the string...

Categories

Resources