Hi I want to add two elements in the class in Python with magic method 'add' and 'radd' ,that they show the time, the elements can be entered in two different formats: in seconds or in the hour format'16: 03: 43 '
Someone can guide me how can i add seconds with format hour:
(65480 seconds + 16:03:43 hour)
class UserTime:
def __init__(self,uTime):
self.time=uTime
self.backup=0
def __add__(self, other):
return self.time + other.time
'''def conv_ToHours(self,seconds):
seconds = seconds % (24 * 3600)
hour = seconds // 3600
seconds %= 3600
minutes = seconds // 60
seconds %= 60
return "%d:%02d:%02d" % (hour, minutes, seconds)'''
def conve_ToSeconds(self):
"""Get seconds from time."""
h, m, s = self.time.split(':')
return int(h) * 3600 + int(m) * 60 + int(s)
def __add__(self, other):
global x
x=int(self.conve_ToSeconds())+int(other.conve_ToSeconds())
return x
def conv_ToHours(self):
if x> 0 :
seconds = x
seconds = seconds % (24 * 3600)
hour = seconds // 3600
seconds %= 3600
minutes = seconds // 60
seconds %= 60
return "%d:%02d:%02d" % (hour, minutes, seconds)
else:
print('Wrong Wrong')
x= int(input('enter time:'))
y = int(input('enter time: '))
I am trying to take a string and convert into 24 hour time. For example, if I am given the string "07:05:45PM", it should return "19:05:45". I have completed all the necessary conversions, I am just not sure how I am supposed to put them all together and have it so that if there were only 5 minutes or 5 seconds, it would place a zero like "xx:05:06".
def timeConversion(s):
nums = s[:8]
hh,mm,ss = [v for v in nums.split(":")]
time = s[8:]
if time == 'AM':
return nums
else:
total = (int(hh) * 3600 + int(mm) * 60 + int(ss)) + 43200
if s == "12:00:00PM":
return nums
hh = total // 3600
mm = total // 60 % 60
ss = total % 60
print(timeConversion("07:05:45PM"))
Only the hours and suffix have any significance in your output. The key is that 12AM is 00, and 12PM is 12. 12:00 is not the only time that deserves this treatment: 12:01 does too. Use the modulo operator to avoid any special cases at all:
def time_conversion(s):
hh = int(s[:2]) % 12 # this is the magical part 12->0
mmss = s[2:8]
suffix = s[8:].strip().upper()
if suffix == 'PM':
hh += 12
return f'{hh:02d}{mmss}'
Here is the working code. For the input "07:05:45PM", it returns "19:05:45". You just need to add a '0' if the minutes or seconds values are less than 10.
def timeConversion(s):
nums = s[:8]
hh,mm,ss = [v for v in nums.split(":")]
time = s[8:]
if time == 'AM':
return nums
else:
total = (int(hh) * 3600+int(mm)*60+int(ss))+43200
if s == "12:00:00PM":
return nums
hh = str(total//3600)
mm = total//60 % 60
ss = total % 60
mm_str = '0'+ str(mm) if mm <= 9 else str(mm)
ss_str = '0'+ str(ss) if ss <= 9 else str(ss)
time_str = str(hh) + ':' + mm_str + ":" + ss_str
return time_str
print(timeConversion("07:05:45PM"))
Since you are dealing with a string, perhaps most of the code could deal with the string.
EDIT: Revised code as per Mad Physicist's comments
def convert(s):
if s[8:] == 'AM':
if s[:2] == '12':
return '00' + s[2:8]
else:
return s[:8]
elif s[8:] == 'PM':
if s[:2] == '12':
return s[:8]
else:
return str(int(s[:2])+ 12) + s[2:8]
for t in ['12:00:00AM', '01:01:01AM', '12:01:01PM', '01:10:11PM', '11:20:20PM']:
print(t, convert(t))
Prints:
12:00:00AM 00:00:00
01:01:01AM 01:01:01
12:01:01PM 12:01:01
01:10:11PM 13:10:11
11:20:20PM 23:20:20
I am having issues with properly implementing the following:
Remove __hours and __minutes.
Adjust the implementation of the mutator and accessor methods. For
example, for __init__(hr, min, sec), validate the values, then set
__seconds = hr * 60 * 60 + min * 60 + sec. This will store the time as seconds. Adjust all the methods to work with __seconds. getSecond()
can use __seconds mod 60 to return only the seconds in the time. Test
all the methods to make sure they still work. (mod is modulus, the
remainder after a division.)
I have used this in my code self.setSecond = (hour * 60 * 60) + (minute * 60 + second)
To properly represent hour, minute and seconds to just seconds I am however having issues with implementing the rest of the program. I'm not sure if I should be printing out just seconds? Also when I change my getSecond() function to return % 60 it is not doing so. I'm assuming because I'm not properly calling it?
Here is my code thus far:
class Clock(object):
def __init__(self, hour, minute, second):
self.setHour(hour)
self.setMinute(minute)
self.setSecond = (hour * 60 * 60) + (minute * 60 + second)
def setHour(self, hour):
self.__hour = hour
if self.__hour > 23:
self.__hour = 0
elif self.__hour < 0:
self.__hour = 0
def getHour(self):
return self.__hour
def setMinute(self, minute):
self.__minute = minute
if self.__minute > 60:
self.__minute = 0
elif self.__minute < 0:
self.__minute = 0
def getMinute(self):
return self.__minute
def setSecond(self, second):
self.__second = second
if self.__second > 60:
self.__second = 0
elif self.__second < 0:
self.__second = 0
def getSecond(self):
return self.__second
def __str__(self):
if self.__hour > 11:
return 'The Time is {}:{}:{} PM'.format(self.__hour, self.__minute, self.__second)
else:
return 'The Time is {}:{}:{} AM'.format(self.__hour, self.__minute, self.setSecond)
stopwatch = Clock(3, 2, 1)
print(stopwatch)
Note: I am aware that this code isn't very pythonic but that is how I was told to keep it (I apologize).
There are 6 changes required primarily:
You don't need to maintain hours and minutes in the class. You maintain only the seconds. So remove the setHour and setMinute methods.
Because you don't maintain the hours and minutes, the getHour and getMinute methods should do the required calculation.
def getHour(self):
return int(self.__second / 3600)
def getMinute(self):
return int(self.__second / 60) % 60
In the init function, call to self.setSecond is not correct. It should be:
def __init__(self, hour, minute, second):
if hour > 23 or hour < 0:
hour = 0
if minute > 60 or minute < 0:
minute = 0
if second > 60 or second < 0:
second = 0
self.setSecond((hour * 60 * 60) + (minute * 60 + second))
And although you mentioned, your getSecond() method does not do a seconds % 60. It should be:
def getSecond(self):
return self.__second % 60
In method def __str__, instead of directly accessing the hours, minutes, seconds, use the accessor methods:
def __str__(self):
if self.getHour() > 11:
return 'The Time is {}:{}:{} PM'.format(self.getHour(), self.getMinute(), self.getSecond())
else:
return 'The Time is {}:{}:{} AM'.format(self.getHour(), self.getMinute(), self.getSecond())
The setSeconds method should not have the check for > 60 because now you will be storing a large number here:
def setSecond(self, second):
self.__second = second
if self.__second < 0:
self.__second = 0
I've been reading posts upon posts of the methods for converting an input number of seconds, which should be output as a formal string with given durations (hours, minutes, seconds). But I want to know how to format it so that it accounts for singularization/pluralization, when I know, for example, 62 seconds should read as "1 minute and 2 seconds" as opposed to 120 seconds which is simply "2 minutes".
One other criteria is that it should return "now" if the seconds is 0.
Here's my code so far:
def format_duration(seconds, granularity = 2):
intervals = (('hours', 3600), ('minutes', 60), ('seconds', 1))
human_time = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
human_time.append("{} {}".format(value, name))
else:
return "now"
return ','.join(human_time[:granularity])
Please help! Thanks!
MJ
Your code already works quite nicely, you just have one problem with your return "now" that I fixed in the code below. What else do you want your code to do?
def prettyList(human_time):
if len(human_time) > 1:
return ' '.join([', '.join(human_time[:-1]), "and", human_time[-1]])
elif len(human_time) == 1:
return human_time[0]
else:
return ""
def format_duration(seconds, granularity = 2):
intervals = (('hours', 3600), ('minutes', 60), ('seconds', 1))
human_time = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
human_time.append("{} {}".format(value, name))
if not human_time:
return "now"
human_time = human_time[:granularity]
return prettyList(human_time)
Edit: so I added a function to prettify the output, the last terms in the list will be separed by a "and" and all the others before by a comma. This will still work even if you add more intervals in your code (like ('days', 86400)). The output now looks like 2 hours, 1 minute and 43 seconds or 25 minutes and 14 seconds.
Made some tweaks for readability :
def pretty_list(human_time):
return human_time[0] if len(human_time) == 1 else ' '.join([', '.join(human_time[:-1]), "and", human_time[-1]])
def get_intervals(seconds):
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
return (
("hour", h),
("minute", m),
("second", s)
)
def format_duration(seconds, granularity=3):
intervals = get_intervals(seconds)
human_time = []
for name, value in intervals:
if value == 0:
continue
elif value == 1:
human_time.append("{} {}".format(value, name))
else:
human_time.append("{} {}s".format(value, name))
return (pretty_list(human_time[:granularity])) if len(human_time) != 0 else "now"
You can try to code for each variation:
def timestamp(ctime):
sec = int(ctime)
if sec == 0:
return "Now"
m, s = divmod(sec, 60)
h, m = divmod(m, 60)
if h == 1: hr_t = 'Hour'
else: hr_t = 'Hours'
if m == 1: mn_t = 'Minute'
else: mn_t = 'Minutes'
if s == 1: sc_t = 'Second'
else: sc_t = 'Seconds'
time_stamp = ""
if h > 0 and m ==0 and s ==0:
time_stamp = "%02d %s " % (h, hr_t)
elif h > 0:
time_stamp = "%02d %s, " % (h, hr_t)
if m > 0 and s !=0:
time_stamp = time_stamp +"%02d %s and %02d %s" % (m, mn_t, s, sc_t)
elif m > 0 and s == 0:
time_stamp = time_stamp +"%02d %s" % (m, mn_t)
elif m == 0 and s != 0:
time_stamp = time_stamp +"%02d %s" % (s, sc_t)
return time_stamp
print (timestamp(11024))
print (timestamp(0))
print (timestamp(31))
print (timestamp(102))
print (timestamp(61))
print (timestamp(60))
print (timestamp(3600))
print (timestamp(3632))
03 Hours, 03 Minutes and 44 Seconds
Now
31 Seconds
01 Minute and 42 Seconds
01 Minute and 01 Second
01 Minute
01 Hour
01 Hour, 32 Seconds
Or you can use the relativedelta option in dateutil and then pick the bones out of it.
from dateutil.relativedelta import relativedelta
attrs = ['years', 'months', 'days', 'hours', 'minutes', 'seconds']
human_readable = lambda delta: ['%d %s ' % (getattr(delta, attr), getattr(delta, attr) != 1 and attr or attr[:-1]) for attr in attrs if getattr(delta, attr) or attr == attrs[-1]]
readable=''
for i in human_readable(relativedelta(seconds=1113600)):
readable += i
print readable
print human_readable(relativedelta(seconds=13600))
print human_readable(relativedelta(seconds=36))
print human_readable(relativedelta(seconds=60))
print human_readable(relativedelta(seconds=3600))
12 days 21 hours 20 minutes 0 seconds
['3 hours ', '46 minutes ', '40 seconds ']
['36 seconds ']
['1 minute ', '0 seconds ']
['1 hour ', '0 seconds ']
For more examples of the second example see: http://code.activestate.com/recipes/578113-human-readable-format-for-a-given-time-delta/
which is where I stole almost all the second set of code from
I found it! I actually needed more intervals - the durations asked for were lengthier than I thought...
def prettyList(human_time):
if len(human_time) > 1:
return ' '.join([', '.join(human_time[:-1]), "and", human_time[-1]])
elif len(human_time) == 1:
return human_time[0]
else:
return ""
def format_duration(seconds, granularity = 4):
intervals = (('years', 29030400), ('months', 2419200), ('weeks', 604800),('days', 86400),('hours', 3600), ('minutes', 60), ('seconds', 1))
human_time = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
human_time.append("{} {}".format(value, name))
if not human_time:
return "now"
human_time = human_time[:granularity]
return prettyList(human_time)
I think that I have covered all of the bases here but I'm sure someone will let me know if I have made an error (large or small) :)
from dateutil.relativedelta import relativedelta
def convertdate(secs):
raw_date = relativedelta(seconds=secs)
years, days = divmod(raw_date.days, 365) # To crudely cater for leap years / 365.2425
hours = raw_date.hours
minutes = raw_date.minutes
seconds = raw_date.seconds
full = [years,days,hours,minutes,seconds]
date_text=['','','','','']
if years == 1: date_text[0] = "Year"
else: date_text[0] = "Years"
if days == 1: date_text[1] = "Day"
else: date_text[1] = "Days"
if hours == 1: date_text[2] = "Hour"
else: date_text[2] = "Hours"
if minutes == 1: date_text[3] = "Minute"
else: date_text[3] = "Minutes"
if seconds == 1: date_text[4] = "Second"
else: date_text[4] = "Seconds"
first_pos = 0
final_pos = 0
element_count = 0
# Find the first and final set positions and the number of returned values
for i in range(5):
if full[i] != 0:
final_pos = i
element_count +=1
if first_pos == 0:
first_pos = i
# Return "now" and any single value
if element_count == 0:
return "Now"
if element_count == 1:
return "%02d %s" % (full[final_pos],date_text[final_pos])
# Initially define the separators
separators=['','','','','']
ret_str=''
for i in range(4):
if full[i] != 0:
separators[i] = ', '
separators[final_pos] = ''
# Redefine the final separator
for i in range(4,-1,-1):
if separators[i] == ', ':
separators[i] = ' and '
break
#Build the readable formatted time string
for i in range(5):
if full[i] != 0:
ret_str += "%02d %s%s" % (full[i],date_text[i],separators[i])
return ret_str
print convertdate(1111113601)
print convertdate(1111113635)
print convertdate(1111113600)
print convertdate(1111111200)
print convertdate(1111104000)
print convertdate(1111104005)
print convertdate(11113240)
print convertdate(11059240)
print convertdate(11113600)
print convertdate(36)
print convertdate(60)
print convertdate(61)
print convertdate(121)
print convertdate(122)
print convertdate(120)
print convertdate(3600)
print convertdate(3601)
35 Years, 85 Days, 02 Hours, 40 Minutes and 01 Second
35 Years, 85 Days, 02 Hours, 40 Minutes and 35 Seconds
35 Years, 85 Days, 02 Hours and 40 Minutes
35 Years, 85 Days and 02 Hours
35 Years and 85 Days
35 Years, 85 Days and 05 Seconds
128 Days, 15 Hours and 40 Seconds
128 Days and 40 Seconds
128 Days, 15 Hours, 06 Minutes and 40 Seconds
36 Seconds
01 Minute
01 Minute and 01 Second
02 Minutes and 01 Second
02 Minutes and 02 Seconds
02 Minutes
01 Hour
01 Hour and 01 Second
So I have this here.
import sys
import os
import time
def clock():
Minutes = 0
Hours = 1
while True:
Minutes += 1
if Minutes == 60:
Minutes = 0
Hours = 2
if Hours == 12:
Hours = 1
Minutes = 0
break
ReadLine = ("\t{0:>2} : {1:>2}\r").format(Hours, Minutes)
sys.stdout.write(ReadLine)
sys.stdout.flush()
time.sleep(60)
clock()
Just for the record, I have made sure that the indentations are correct, they look a little screwy here. And I realize that I have nothing set for A.M./P.M. as of yet.. Any help is appreciated for this noob.
Thank you - Matt.
Edit:
>>> 2: 0 2: 0 2: 0
This is what is printing out now, the minutes have not updated. I'm obviously missing something. Once again thanks for any help, and I am sorry if this is a repeat, I have searched for an answer, but none was found. Thanks - Matt.
Edit #2- I figured it out. I used a bit of both of the answers, and whilst I accept the fact that it will be slow it does what I want it to do.
import sys
import os
import time
def clock():
Minutes = 0
Hours = 1
AM_PM = "AM" if Hours < 12 else "P.M"
while True:
Minutes += 1
if Minutes == 60:
Minutes = 0
Hours += 1
if Hours == 24:
Hours = 1
Minutes = 0
break
ReadLine = ("\t{:>2} : {:>2} {}\r").format(Hours, Minutes, AM_PM)
sys.stdout.write(ReadLine)
sys.stdout.flush()
time.sleep(60)
clock()
You know, it seems no matter how hard I try, I cannot get this darned indentation to look right. Oh well, I hope you can understand it's just tabbed a bit to the right.
your code print nothing because you put the code that print to stdout inside the if statements. so it would print only when Minutes == 60 and Hours == 12 (which will never happend because of you dont increament Hours as meantioned in the comments.
try this:
import sys
import os
import time
def clock():
Minutes = 0
Hours = 1
ampm = "AM"
while True:
Minutes += 1
if Minutes == 60:
Minutes = 0
Hours += 1
if Hours == 12:
Hours = 1
Minutes = 0
ampm = ("AM" if (ampm == "PM") else "PM")
ReadLine = ("\t{0:>2} : {1:>2} {2} \r").format(Hours, Minutes,ampm)
sys.stdout.write(ReadLine)
sys.stdout.flush()
time.sleep(60)
clock()
import datetime
then = now = datetime.datetime.now()
minutes = 0
hours = 0
while True:
now = datetime.datetime.now()
if (now-then).total_seconds() > 60:
then += datetime.timedelta(minutes=1)
minutes += 1
if minutes == 60:
minutes = 0
hours += 1
if hours == 24:
hours = 0
am_pm = "AM" if hours < 12 else "PM"
print("{:>2}:{:>02} {}".format((hours+11)%12+1, minutes, am_pm))
Note that I do away with time.sleep as it's not guaranteed to sleep for exactly the time requested (indeed you will always be running slightly slow by that clock) and instead compare a current time to the last time a minute passed and see if the total seconds are more than 60. If so, increment minutes, if minutes is 60, increment hours and check for rollover and am_pm switch. Afterwards, print the time.
If you're wanting to stretch your legs a little, try implementing it in a class! Ooh ooh, and threading too!
import datetime
import threading
import queue
class Clock(object):
def __init__(self, current_time=None):
if isinstance(current_time, datetime.datetime):
hours, minutes = current_time.hour, current_time.minute
else:
hours = minutes = 0
self.hours = hours
self.minutes = minutes
self.q = queue.Queue()
def checkTime(self):
try:
self.q.get_nowait() # time has updated, or exception thrown
self.updateTime()
self.q.task_done()
except queue.Empty:
pass # time hasn't updated
def updateTime(self, num_mins=1):
self.minutes += 1
if self.minutes == 60:
self.minutes = 0
self.hours += 1
if self.hours == 24:
self.hours = 0
print(self)
def minutePassed(self):
then = datetime.datetime.now()
while True:
now = datetime.datetime.now()
if (now-then).total_seconds() > 60:
then += datetime.timedelta(minutes=1)
self.q.put('_') # put something there, doesn't matter what
def __str__(self):
am_pm = "AM" if self.hours < 12 else "PM"
return "{:>2}:{:>02} {}".format((self.hours+11)%12+1,
self.minutes, am_pm)
def start(self):
t = threading.Thread(target=self.minutePassed)
t.daemon=True
t.start()
while True:
self.checkTime()
clock = Clock(datetime.datetime.now())
clock.start()