Readable Time Format (w/ Good Grammar!)
<p>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, <code>62</code> seconds should read as <code>"1 minute and 2 seconds"</code> as opposed to <code>120</code> seconds which is simply <code>"2 minutes"</code>.</p>

<p>One other criteria is that it should return <code>"now"</code> if the seconds is <code>0</code>. </p>

<p>Here's my code so far: </p>

<pre><code>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])
</code></pre>

<p>Please help! Thanks! </p>

<p>MJ</p>

<p>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) :)</p>

<pre><code>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
</code></pre>

python time control-flow