Function to convert seconds into minutes, hours, and days
Question: Write a program that asks the user to enter a number of seconds, and works as follows:
There are 60 seconds in a minute. If the number of seconds entered by the user is greater than or equal to 60, the program should display the number of minutes in that many seconds.
There are 3600 seconds in an hour. If the number of seconds entered by the user is greater than or equal to 3600, the program should display the number of hours in that many seconds.
There are 86400 seconds in a day. If the number of seconds开发者_开发知识库 entered by the user is greater than or equal to 86400, the program should display the number of days in that many seconds.
What I have so far:
def time():
sec = int( input ('Enter the number of seconds:'.strip())
if sec <= 60:
minutes = sec // 60
print('The number of minutes is {0:.2f}'.format(minutes))
if sec (<= 3600):
hours = sec // 3600
print('The number of minutes is {0:.2f}'.format(hours))
if sec <= 86400:
days = sec // 86400
print('The number of minutes is {0:.2f}'.format(days))
return
This tidbit is useful for displaying elapsed time to varying degrees of granularity.
I personally think that questions of efficiency are practically meaningless here, so long as something grossly inefficient isn't being done. Premature optimization is the root of quite a bit of evil. This is fast enough that it'll never be your choke point.
intervals = (
('weeks', 604800), # 60 * 60 * 24 * 7
('days', 86400), # 60 * 60 * 24
('hours', 3600), # 60 * 60
('minutes', 60),
('seconds', 1),
)
def display_time(seconds, granularity=2):
result = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
result.append("{} {}".format(value, name))
return ', '.join(result[:granularity])
..and this provides decent output:
In [52]: display_time(1934815)
Out[52]: '3 weeks, 1 day'
In [53]: display_time(1934815, 4)
Out[53]: '3 weeks, 1 day, 9 hours, 26 minutes'
This will convert n seconds into d days, h hours, m minutes, and s seconds.
from datetime import datetime, timedelta
def GetTime():
sec = timedelta(seconds=int(input('Enter the number of seconds: ')))
d = datetime(1,1,1) + sec
print("DAYS:HOURS:MIN:SEC")
print("%d:%d:%d:%d" % (d.day-1, d.hour, d.minute, d.second))
def normalize_seconds(seconds: int) -> tuple:
(days, remainder) = divmod(seconds, 86400)
(hours, remainder) = divmod(remainder, 3600)
(minutes, seconds) = divmod(remainder, 60)
return namedtuple("_", ("days", "hours", "minutes", "seconds"))(days, hours, minutes, seconds)
I'm not entirely sure if you want it, but I had a similar task and needed to remove a field if it is zero. For example, 86401 seconds would show "1 days, 1 seconds" instead of "1 days, 0 hours, 0 minutes, 1 seconds". THe following code does that.
def secondsToText(secs):
days = secs//86400
hours = (secs - days*86400)//3600
minutes = (secs - days*86400 - hours*3600)//60
seconds = secs - days*86400 - hours*3600 - minutes*60
result = ("{} days, ".format(days) if days else "") + \
("{} hours, ".format(hours) if hours else "") + \
("{} minutes, ".format(minutes) if minutes else "") + \
("{} seconds, ".format(seconds) if seconds else "")
return result
EDIT: a slightly better version that handles pluralization of words.
def secondsToText(secs):
days = secs//86400
hours = (secs - days*86400)//3600
minutes = (secs - days*86400 - hours*3600)//60
seconds = secs - days*86400 - hours*3600 - minutes*60
result = ("{0} day{1}, ".format(days, "s" if days!=1 else "") if days else "") + \
("{0} hour{1}, ".format(hours, "s" if hours!=1 else "") if hours else "") + \
("{0} minute{1}, ".format(minutes, "s" if minutes!=1 else "") if minutes else "") + \
("{0} second{1}, ".format(seconds, "s" if seconds!=1 else "") if seconds else "")
return result
EDIT2: created a gist that does that in several languages
To convert seconds (as string) into datetime, this could also help. You get number of days and seconds. Seconds can be further converted into minutes and hours.
from datetime import datetime, timedelta
sec = timedelta(seconds=(int(input('Enter the number of seconds: '))))
time = str(sec)
def seconds_to_dhms(time):
seconds_to_minute = 60
seconds_to_hour = 60 * seconds_to_minute
seconds_to_day = 24 * seconds_to_hour
days = time // seconds_to_day
time %= seconds_to_day
hours = time // seconds_to_hour
time %= seconds_to_hour
minutes = time // seconds_to_minute
time %= seconds_to_minute
seconds = time
print("%d days, %d hours, %d minutes, %d seconds" % (days, hours, minutes, seconds))
time = int(input("Enter the number of seconds: "))
seconds_to_dhms(time)
Output: Enter the number of seconds: 2434234232
Result: 28174 days, 0 hours, 10 minutes, 32 seconds
def convertSeconds(seconds):
h = seconds//(60*60)
m = (seconds-h*60*60)//60
s = seconds-(h*60*60)-(m*60)
return [h, m, s]
The function input is a number of seconds, and the return is a list of hours, minutes and seconds which that amount of seconds represent.
seconds_in_day = 86400
seconds_in_hour = 3600
seconds_in_minute = 60
seconds = int(input("Enter a number of seconds: "))
days = seconds // seconds_in_day
seconds = seconds - (days * seconds_in_day)
hours = seconds // seconds_in_hour
seconds = seconds - (hours * seconds_in_hour)
minutes = seconds // seconds_in_minute
seconds = seconds - (minutes * seconds_in_minute)
print("{0:.0f} days, {1:.0f} hours, {2:.0f} minutes, {3:.0f} seconds.".format(
days, hours, minutes, seconds))
Although divmod() has been mentioned, I didn't see what I considered to be a nice example. Here's mine:
q=972021.0000 # For example
days = divmod(q, 86400)
# days[0] = whole days and
# days[1] = seconds remaining after those days
hours = divmod(days[1], 3600)
minutes = divmod(hours[1], 60)
print "%i days, %i hours, %i minutes, %i seconds" % (days[0], hours[0], minutes[0], minutes[1])
Which outputs:
11 days, 6 hours, 0 minutes, 21 seconds
#1 min = 60
#1 hour = 60 * 60 = 3600
#1 day = 60 * 60 * 24 = 86400
x=input('enter a positive integer: ')
t=int(x)
day= t//86400
hour= (t-(day*86400))//3600
minit= (t - ((day*86400) + (hour*3600)))//60
seconds= t - ((day*86400) + (hour*3600) + (minit*60))
print( day, 'days' , hour,' hours', minit, 'minutes',seconds,' seconds')
At first glance, I figured divmod would be faster since it's a single statement and a built-in function, but timeit seems to show otherwise. Consider this little example I came up with when I was trying to figure out the fastest method for use in a loop that continuously runs in a gobject idle_add splitting a seconds counter into a human readable time for updating a progress bar label.
import timeit
def test1(x,y, dropy):
while x > 0:
y -= dropy
x -= 1
# the test
minutes = (y-x) / 60
seconds = (y-x) % 60.0
def test2(x,y, dropy):
while x > 0:
y -= dropy
x -= 1
# the test
minutes, seconds = divmod((y-x), 60)
x = 55 # litte number, also number of tests
y = 10000 # make y > x by factor of drop
dropy = 7 # y is reduced this much each iteration, for variation
print "division and modulus:", timeit.timeit( lambda: test1(x,y,dropy) )
print "divmod function:", timeit.timeit( lambda: test2(x,y,dropy) )
The built-in divmod function seems incredibly slower compared to using the simple division and modulus.
division and modulus: 12.5737669468
divmod function: 17.2861430645
These functions are fairly compact and only use standard Python 2.6 and later.
def ddhhmmss(seconds):
"""Convert seconds to a time string "[[[DD:]HH:]MM:]SS".
"""
dhms = ''
for scale in 86400, 3600, 60:
result, seconds = divmod(seconds, scale)
if dhms != '' or result > 0:
dhms += '{0:02d}:'.format(result)
dhms += '{0:02d}'.format(seconds)
return dhms
def seconds(dhms):
"""Convert a time string "[[[DD:]HH:]MM:]SS" to seconds.
"""
components = [int(i) for i in dhms.split(':')]
pad = 4 - len(components)
if pad < 0:
raise ValueError('Too many components to match [[[DD:]HH:]MM:]SS')
components = [0] * pad + components
return sum(i * j for i, j in zip((86400, 3600, 60, 1), components))
And here are tests to go with them. I'm using the pytest package as a simple way to test exceptions.
import ddhhmmss
import pytest
def test_ddhhmmss():
assert ddhhmmss.ddhhmmss(0) == '00'
assert ddhhmmss.ddhhmmss(2) == '02'
assert ddhhmmss.ddhhmmss(12 * 60) == '12:00'
assert ddhhmmss.ddhhmmss(3600) == '01:00:00'
assert ddhhmmss.ddhhmmss(10 * 86400) == '10:00:00:00'
assert ddhhmmss.ddhhmmss(86400 + 5 * 3600 + 30 * 60 + 1) == '01:05:30:01'
assert ddhhmmss.ddhhmmss(365 * 86400) == '365:00:00:00'
def test_seconds():
assert ddhhmmss.seconds('00') == 0
assert ddhhmmss.seconds('02') == 2
assert ddhhmmss.seconds('12:00') == 12 * 60
assert ddhhmmss.seconds('01:00:00') == 3600
assert ddhhmmss.seconds('1:0:0') == 3600
assert ddhhmmss.seconds('3600') == 3600
assert ddhhmmss.seconds('60:0') == 3600
assert ddhhmmss.seconds('10:00:00:00') == 10 * 86400
assert ddhhmmss.seconds('1:05:30:01') == 86400 + 5 * 3600 + 30 * 60 + 1
assert ddhhmmss.seconds('365:00:00:00') == 365 * 86400
def test_seconds_raises():
with pytest.raises(ValueError):
ddhhmmss.seconds('')
with pytest.raises(ValueError):
ddhhmmss.seconds('foo')
with pytest.raises(ValueError):
ddhhmmss.seconds('1:00:00:00:00')
Patching Mr.B's answer (sorry, not enough rep. to comment), we can return variable granularity based on the amount of time. For example, we don't say "1 week, 5 seconds", we just say "1 week":
def display_time(seconds, granularity=2):
result = []
for name, count in intervals:
value = seconds // count
if value:
seconds -= value * count
if value == 1:
name = name.rstrip('s')
result.append("{} {}".format(value, name))
else:
# Add a blank if we're in the middle of other values
if len(result) > 0:
result.append(None)
return ', '.join([x for x in result[:granularity] if x is not None])
Some sample input:
for diff in [5, 67, 3600, 3605, 3667, 24*60*60, 24*60*60+5, 24*60*60+57, 24*60*60+3600, 24*60*60+3667, 2*24*60*60, 2*24*60*60+5*60*60, 7*24*60*60, 7*24*60*60 + 24*60*60]:
print "For %d seconds: %s" % (diff, display_time(diff, 2))
...returns this output:
For 5 seconds: 5 seconds
For 67 seconds: 1 minute, 7 seconds
For 3600 seconds: 1 hour
For 3605 seconds: 1 hour
For 3667 seconds: 1 hour, 1 minute
For 86400 seconds: 1 day
For 86405 seconds: 1 day
For 86457 seconds: 1 day
For 90000 seconds: 1 day, 1 hour
For 90067 seconds: 1 day, 1 hour
For 172800 seconds: 2 days
For 190800 seconds: 2 days, 5 hours
For 604800 seconds: 1 week
For 691200 seconds: 1 week, 1 day
Do it the other way around subtracting the secs as needed, and don't call it time; there's a package with that name:
def sec_to_time():
sec = int( input ('Enter the number of seconds:'.strip()) )
days = sec / 86400
sec -= 86400*days
hrs = sec / 3600
sec -= 3600*hrs
mins = sec / 60
sec -= 60*mins
print days, ':', hrs, ':', mins, ':', sec
time_in_sec = 65 #I took time as 65 sec for example
day = divmod(time_in_sec, 86_400)
hour = divmod(day[1], 3_600)
min = divmod(hour[1], 60)
sec = min[1]
print(f"Day {day[0]} |Hour {hour[0]} |Min {min[0]} |Sec {sec}")
Explanation:
divmod(x, y)
function returns (x//y, x%y)
In day
variable the x//y
is the number of days and the x%y
is the remaining seconds.
So for the hour
variable the remainder of the day
variable is the input. Likewise you can calculate up to a week using this simple program.
The "timeit" answer above that declares divmod to be slower has seriously flawed logic.
Test1 calls operators.
Test2 calls the function divmod, and calling a function has overhead.
A more accurate way to test would be:
import timeit
def moddiv(a,b):
q= a/b
r= a%b
return q,r
a=10
b=3
md=0
dm=0
for i in range(1,10):
c=a*i
md+= timeit.timeit( lambda: moddiv(c,b))
dm+=timeit.timeit( lambda: divmod(c,b))
print("moddiv ", md)
print("divmod ", dm)
moddiv 5.806157339000492
divmod 4.322451676005585
divmod is faster.
Patching as well Ralph Bolton's answer. Moving to a class and moving tulp of tulp (intervals) to dictionary. Adding an optional rounded function depending of granularity (enable by default). Ready to translation using gettext (default is disable). This is intend to be load from an module. This is for python3 (tested 3.6 - 3.8)
import gettext
import locale
from itertools import chain
mylocale = locale.getdefaultlocale()
# see --> https://stackoverflow.com/a/10174657/11869956 thx
#localedir = os.path.join(os.path.dirname(__file__), 'locales')
# or python > 3.4:
try:
localedir = pathlib.Path(__file__).parent/'locales'
lang_translations = gettext.translation('utils', localedir,
languages=[mylocale[0]])
lang_translations.install()
_ = lang_translations.gettext
except Exception as exc:
print('Error: unexcept error while initializing translation:', file=sys.stderr)
print(f'Error: {exc}', file=sys.stderr)
print(f'Error: localedir={localedir}, languages={mylocale[0]}', file=sys.stderr)
print('Error: translation has been disabled.', file=sys.stderr)
_ = gettext.gettext
Here is the class:
class FormatTimestamp:
"""Convert seconds to, optional rounded, time depending of granularity's degrees.
inspired by https://stackoverflow.com/a/24542445/11869956"""
def __init__(self):
# For now i haven't found a way to do it better
# TODO: optimize ?!? ;)
self.intervals = {
# 'years' : 31556952, # https://www.calculateme.com/time/years/to-seconds/
# https://www.calculateme.com/time/months/to-seconds/ -> 2629746 seconds
# But it's outputing some strange result :
# So 3 seconds less (2629743) : 4 weeks, 2 days, 10 hours, 29 minutes and 3 seconds
# than after 3 more seconds : 1 month ?!?
# Google give me 2628000 seconds
# So 3 seconds less (2627997): 4 weeks, 2 days, 9 hours, 59 minutes and 57 seconds
# Strange as well
# So for the moment latest is week ...
#'months' : 2419200, # 60 * 60 * 24 * 7 * 4
'weeks' : 604800, # 60 * 60 * 24 * 7
'days' : 86400, # 60 * 60 * 24
'hours' : 3600, # 60 * 60
'minutes' : 60,
'seconds' : 1
}
self.nextkey = {
'seconds' : 'minutes',
'minutes' : 'hours',
'hours' : 'days',
'days' : 'weeks',
'weeks' : 'weeks',
#'months' : 'months',
#'years' : 'years' # stop here
}
self.translate = {
'weeks' : _('weeks'),
'days' : _('days'),
'hours' : _('hours'),
'minutes' : _('minutes'),
'seconds' : _('seconds'),
## Single
'week' : _('week'),
'day' : _('day'),
'hour' : _('hour'),
'minute' : _('minute'),
'second' : _('second'),
' and' : _('and'),
',' : _(','), # This is for compatibility
'' : '\0' # same here BUT we CANNOT pass empty string to gettext
# or we get : warning: Empty msgid. It is reserved by GNU gettext:
# gettext("") returns the header entry with
# meta information, not the empty string.
# Thx to --> https://stackoverflow.com/a/30852705/11869956 - saved my day
}
def convert(self, seconds, granularity=2, rounded=True, translate=False):
"""Proceed the conversion"""
def _format(result):
"""Return the formatted result
TODO : numpy / google docstrings"""
start = 1
length = len(result)
none = 0
next_item = False
for item in reversed(result[:]):
if item['value']:
# if we have more than one item
if length - none > 1:
# This is the first 'real' item
if start == 1:
item['punctuation'] = ''
next_item = True
elif next_item:
# This is the second 'real' item
# Happened 'and' to key name
item['punctuation'] = ' and'
next_item = False
# If there is more than two 'real' item
# than happened ','
elif 2 < start:
item['punctuation'] = ','
else:
item['punctuation'] = ''
else:
item['punctuation'] = ''
start += 1
else:
none += 1
return [ { 'value' : mydict['value'],
'name' : mydict['name_strip'],
'punctuation' : mydict['punctuation'] } for mydict in result \
if mydict['value'] is not None ]
def _rstrip(value, name):
"""Rstrip 's' name depending of value"""
if value == 1:
name = name.rstrip('s')
return name
# Make sure granularity is an integer
if not isinstance(granularity, int):
raise ValueError(f'Granularity should be an integer: {granularity}')
# For seconds only don't need to compute
if seconds < 0:
return 'any time now.'
elif seconds < 60:
return 'less than a minute.'
result = []
for name, count in self.intervals.items():
value = seconds // count
if value:
seconds -= value * count
name_strip = _rstrip(value, name)
# save as dict: value, name_strip (eventually strip), name (for reference), value in seconds
# and count (for reference)
result.append({
'value' : value,
'name_strip' : name_strip,
'name' : name,
'seconds' : value * count,
'count' : count
})
else:
if len(result) > 0:
# We strip the name as second == 0
name_strip = name.rstrip('s')
# adding None to key 'value' but keep other value
# in case when need to add seconds when we will
# recompute every thing
result.append({
'value' : None,
'name_strip' : name_strip,
'name' : name,
'seconds' : 0,
'count' : count
})
# Get the length of the list
length = len(result)
# Don't need to compute everything / every time
if length < granularity or not rounded:
if translate:
return ' '.join('{0} {1}{2}'.format(item['value'], _(self.translate[item['name']]),
_(self.translate[item['punctuation']])) \
for item in _format(result))
else:
return ' '.join('{0} {1}{2}'.format(item['value'], item['name'], item['punctuation']) \
for item in _format(result))
start = length - 1
# Reverse list so the firsts elements
# could be not selected depending on granularity.
# And we can delete item after we had his seconds to next
# item in the current list (result)
for item in reversed(result[:]):
if granularity <= start <= length - 1:
# So we have to round
current_index = result.index(item)
next_index = current_index - 1
# skip item value == None
# if the seconds of current item is superior
# to the half seconds of the next item: round
if item['value'] and item['seconds'] > result[next_index]['count'] // 2:
# +1 to the next item (in seconds: depending on item count)
result[next_index]['seconds'] += result[next_index]['count']
# Remove item which is not selected
del result[current_index]
start -= 1
# Ok now recalculate everything
# Reverse as well
for item in reversed(result[:]):
# Check if seconds is superior or equal to the next item
# but not from 'result' list but from 'self.intervals' dict
# Make sure it's not None
if item['value']:
next_item_name = self.nextkey[item['name']]
# This mean we are at weeks
if item['name'] == next_item_name:
# Just recalcul
item['value'] = item['seconds'] // item['count']
item['name_strip'] = _rstrip(item['value'], item['name'])
# Stop to weeks to stay 'right'
elif item['seconds'] >= self.intervals[next_item_name]:
# First make sure we have the 'next item'
# found via --> https://stackoverflow.com/q/26447309/11869956
# maybe there is a faster way to do it ? - TODO
if any(search_item['name'] == next_item_name for search_item in result):
next_item_index = result.index(item) - 1
# Append to
result[next_item_index]['seconds'] += item['seconds']
# recalculate value
result[next_item_index]['value'] = result[next_item_index]['seconds'] // \
result[next_item_index]['count']
# strip or not
result[next_item_index]['name_strip'] = _rstrip(result[next_item_index]['value'],
result[next_item_index]['name'])
else:
# Creating
next_item_index = result.index(item) - 1
# get count
next_item_count = self.intervals[next_item_name]
# convert seconds
next_item_value = item['seconds'] // next_item_count
# strip 's' or not
next_item_name_strip = _rstrip(next_item_value, next_item_name)
# added to dict
next_item = {
'value' : next_item_value,
'name_strip' : next_item_name_strip,
'name' : next_item_name,
'seconds' : item['seconds'],
'count' : next_item_count
}
# insert to the list
result.insert(next_item_index, next_item)
# Remove current item
del result[result.index(item)]
else:
# for current item recalculate
# keys 'value' and 'name_strip'
item['value'] = item['seconds'] // item['count']
item['name_strip'] = _rstrip(item['value'], item['name'])
if translate:
return ' '.join('{0} {1}{2}'.format(item['value'],
_(self.translate[item['name']]),
_(self.translate[item['punctuation']])) \
for item in _format(result))
else:
return ' '.join('{0} {1}{2}'.format(item['value'], item['name'], item['punctuation']) \
for item in _format(result))
To use it:
myformater = FormatTimestamp()
myconverter = myformater.convert(seconds)
granularity = 1 - 5, rounded = True / False, translate = True / False
Some test to show difference:
myformater = FormatTimestamp()
for firstrange in [131440, 563440, 604780, 2419180, 113478160]:
print(f'#### Seconds : {firstrange} ####')
print('\tFull - function: {0}'.format(display_time(firstrange, granularity=5)))
print('\tFull - class: {0}'.format(myformater.convert(firstrange, granularity=5)))
for secondrange in range(1, 6, 1):
print('\tGranularity this answer ({0}): {1}'.format(secondrange,
myformater.convert(firstrange,
granularity=secondrange, translate=False)))
print('\tGranularity Bolton\'s answer ({0}): {1}'.format(secondrange, display_time(firstrange,
granularity=secondrange)))
print()
Seconds : 131440Seconds : 563440Full - function: 1 day, 12 hours, 30 minutes, 40 seconds Full - class: 1 day, 12 hours, 30 minutes and 40 seconds Granularity this answer (1): 2 days Granularity Bolton's answer (1): 1 day Granularity this answer (2): 1 day and 13 hours Granularity Bolton's answer (2): 1 day, 12 hours Granularity this answer (3): 1 day, 12 hours and 31 minutes Granularity Bolton's answer (3): 1 day, 12 hours, 30 minutes Granularity this answer (4): 1 day, 12 hours, 30 minutes and 40 seconds Granularity Bolton's answer (4): 1 day, 12 hours, 30 minutes, 40 seconds Granularity this answer (5): 1 day, 12 hours, 30 minutes and 40 seconds Granularity Bolton's answer (5): 1 day, 12 hours, 30 minutes, 40 seconds
Full - function: 6 days, 12 hours, 30 minutes, 40 seconds
Full - class: 6 days, 12 hours, 30 minutes and 40 seconds
Granularity this answer (1): 1 week
Granularity Bolton's answer (1): 6 days
Granularity this answer (2): 6 days and 13 hours
Granularity Bolton's answer (2): 6 days, 12 hours
Granularity this answer (3): 6 days, 12 hours and 31 minutes
Granularity Bolton's answer (3): 6 days, 12 hours, 30 minutes
Granularity this answer (4): 6 days, 12 hours, 30 minutes and 40 seconds
Granularity Bolton's answer (4): 6 days, 12 hours, 30 minutes, 40 seconds
Granularity this answer (5): 6 days, 12 hours, 30 minutes and 40 seconds
Granularity Bolton's answer (5): 6 days, 12 hours, 30 minutes, 40 seconds
Seconds : 604780
Full - function: 6 days, 23 hours, 59 minutes, 40 seconds
Full - class: 6 days, 23 hours, 59 minutes and 40 seconds
Granularity this answer (1): 1 week
Granularity Bolton's answer (1): 6 days
Granularity this answer (2): 1 week
Granularity Bolton's answer (2): 6 days, 23 hours
Granularity this answer (3): 1 week
Granularity Bolton's answer (3): 6 days, 23 hours, 59 minutes
Granularity this answer (4): 6 days, 23 hours, 59 minutes and 40 seconds
Granularity Bolton's answer (4): 6 days, 23 hours, 59 minutes, 40 seconds
Granularity this answer (5): 6 days, 23 hours, 59 minutes and 40 seconds
Granularity Bolton's answer (5): 6 days, 23 hours, 59 minutes, 40 seconds
Seconds : 2419180
Full - function: 3 weeks, 6 days, 23 hours, 59 minutes, 40 seconds
Full - class: 3 weeks, 6 days, 23 hours, 59 minutes and 40 seconds
Granularity this answer (1): 4 weeks
Granularity Bolton's answer (1): 3 weeks
Granularity this answer (2): 4 weeks
Granularity Bolton's answer (2): 3 weeks, 6 days
Granularity this answer (3): 4 weeks
Granularity Bolton's answer (3): 3 weeks, 6 days, 23 hours
Granularity this answer (4): 4 weeks
Granularity Bolton's answer (4): 3 weeks, 6 days, 23 hours, 59 minutes
Granularity this answer (5): 3 weeks, 6 days, 23 hours, 59 minutes and 40 seconds
Granularity Bolton's answer (5): 3 weeks, 6 days, 23 hours, 59 minutes, 40 seconds
Seconds : 113478160
Full - function: 187 weeks, 4 days, 9 hours, 42 minutes, 40 seconds
Full - class: 187 weeks, 4 days, 9 hours, 42 minutes and 40 seconds
Granularity this answer (1): 188 weeks
Granularity Bolton's answer (1): 187 weeks
Granularity this answer (2): 187 weeks and 4 days
Granularity Bolton's answer (2): 187 weeks, 4 days
Granularity this answer (3): 187 weeks, 4 days and 10 hours
Granularity Bolton's answer (3): 187 weeks, 4 days, 9 hours
Granularity this answer (4): 187 weeks, 4 days, 9 hours and 43 minutes
Granularity Bolton's answer (4): 187 weeks, 4 days, 9 hours, 42 minutes
Granularity this answer (5): 187 weeks, 4 days, 9 hours, 42 minutes and 40 seconds
Granularity Bolton's answer (5): 187 weeks, 4 days, 9 hours, 42 minutes, 40 seconds
I have a french translation ready. But it's fast to do the translation ... just few words. Hope this could help as the other answer help me a lot.
This is like Bolton
's answer but with a few additions...
- stored ratios in a dictionary instead of a tuple for better readability.
- added an if check for
0
seconds input. - added an if check to change the last
,
withand
for complete grammar.
def secondsToText(unit, granularity = 2):
ratios = {
'decades' : 311040000, # 60 * 60 * 24 * 30 * 12 * 10
'years' : 31104000, # 60 * 60 * 24 * 30 * 12
'months' : 2592000, # 60 * 60 * 24 * 30
'days' : 86400, # 60 * 60 * 24
'hours' : 3600, # 60 * 60
'minutes' : 60, # 60
'seconds' : 1 # 1
}
texts = []
for ratio in ratios:
result, unit = divmod(unit, ratios[ratio])
if result:
if result == 1:
ratio = ratio.rstrip('s')
texts.append(f'{result} {ratio}')
texts = texts[:granularity]
if not texts:
return f'0 {list(ratios)[-1]}'
text = ', '.join(texts)
if len(texts) > 1:
index = text.rfind(',')
text = f'{text[:index]} and {text[index + 1:]}'
return text
Python 3 solution
def seconds_to_dhms(total_seconds: int) -> str:
seconds = total_seconds % 60
total_minutes = total_seconds // 60
total_hours = total_minutes // 60
minutes = total_minutes % 60
days = total_hours // 24
hours = total_hours % 24
return f"{days} days and {hours} hour and {minutes} minutes and {seconds} seconds."
精彩评论