【问题标题】:Python function to convert seconds into minutes, hours, and days将秒转换为分钟、小时和天的 Python 函数
【发布时间】:2011-05-02 05:02:08
【问题描述】:

问题: 编写一个程序,要求用户输入秒数,其工作原理如下:

  • 一分钟有 60 秒。如果用户输入的秒数大于或等于 60,则程序应显示该秒数中的分钟数。

  • 一小时有 3600 秒。如果用户输入的秒数大于或等于 3600,则程序应显示该秒数中的小时数。

  • 一天有 86400 秒。如果用户输入的秒数大于或等于 86400,则程序应显示该秒数中的天数。

到目前为止我所拥有的:

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

【问题讨论】:

标签: python


【解决方案1】:

这个花絮对于以不同程度的粒度显示经过的时间很有用。

我个人认为效率问题在这里实际上毫无意义,只要不做一些非常低效的事情。过早的优化是万恶之源。这速度足够快,永远不会成为您的瓶颈。

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])

..这提供了不错的输出:

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'

【讨论】:

  • 在我的 Python 2.6.6 系统上,我不得不使用 result.append("%s %s" % (value, name))
【解决方案2】:

这会将 n 秒转换为 d 天、h 小时、m 分钟和 s 秒。

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))

【讨论】:

  • 我相信秒数是最大的。所以这不是建议的方式。请参阅文档: seconds 介于 0 和 86399(含)docs.python.org/library/datetime.html
  • 一天有86400秒,所以你只能有0-86399秒。换句话说,timedelta(seconds=86400) 将解析为 days=1, seconds=0。因此,86399 不是秒的最大输入值。
  • 如果持续时间太长以至于它改变了月份,那么这个建议将不起作用。尝试 5184000 (60*24*3600) 秒。
  • 使用3.0风格的格式字符串,可以使用:t = timedelta(seconds=long(valu)); print("Time to Keep: {}m-{}d {} (h:mm:ss)".format(t.days/30, t.days%30, timedelta(seconds=t.seconds)))
  • 工作时间最长为 2678399 秒(含),大约为 1 个月。更高的数字失败。除非您需要更多功能,否则只需添加 assert
【解决方案3】:

我不完全确定你是否想要它,但我有一个类似的任务,如果字段为零,我需要删除它。例如,86401 秒将显示“1 天 1 秒”而不是“1 天 0 小时 0 分钟 1 秒”。下面的代码就是这样做的。

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

编辑:处理单词复数的稍微好一点的版本。

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:创建了一个gist,它可以用多种语言来实现

【讨论】:

    【解决方案4】:

    要将秒(作为字符串)转换为日期时间,这也可能有所帮助。你得到天数和秒数。秒可以进一步转换为分钟和小时。

    from datetime import datetime, timedelta
    sec = timedelta(seconds=(int(input('Enter the number of seconds: '))))
    time = str(sec)
    

    【讨论】:

    • 我得到一个 TypeError,来解决这个问题:sec = timedelta(seconds=(int(input('Enter the number of seconds: '))))
    【解决方案5】:
    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)
    

    输出: 输入秒数:2434234232

    结果: 28174 天 0 小时 10 分钟 32 秒

    【讨论】:

      【解决方案6】:
      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)
      

      【讨论】:

        【解决方案7】:
        def convertSeconds(seconds):
            h = seconds//(60*60)
            m = (seconds-h*60*60)//60
            s = seconds-(h*60*60)-(m*60)
            return [h, m, s]
        

        函数输入是秒数,返回是一个小时、分钟和秒的列表,该秒数代表。

        【讨论】:

          【解决方案8】:
          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))
          

          【讨论】:

          • 只发布代码作为答案是不好的。你也应该包括一些解释,即使你认为它可能是不言而喻的。
          【解决方案9】:

          虽然已经提到了 divmod(),但我没有看到我认为是一个很好的例子。这是我的:

          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])
          

          哪些输出:

          11 days, 6 hours, 0 minutes, 21 seconds
          

          【讨论】:

            【解决方案10】:
            #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')
            

            【讨论】:

              【解决方案11】:

              乍一看,我认为 divmod 会更快,因为它是一个语句和一个内置函数,但 timeit 似乎另有说明。考虑一下这个小例子,当我试图找出在循环中使用的最快方法时,该方法在 gobject idle_add 中连续运行,将秒计数器拆分为人类可读的时间以更新进度条标签。

              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) )
              

              与使用简单的除法和模数相比,内置的 divmod 函数似乎慢得多。

              division and modulus: 12.5737669468
              divmod function: 17.2861430645
              

              【讨论】:

                【解决方案12】:

                这些函数相当紧凑,仅使用标准 Python 2.6 及更高版本。

                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))
                

                这里有一些测试。我使用 pytest 包作为测试异常的简单方法。

                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')
                

                【讨论】:

                  【解决方案13】:

                  修补Mr.B's answer(抱歉,没有足够的代表发表评论),我们可以根据时间量返回可变粒度。例如,我们不说“1 周,5 秒”,我们只说“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))
                          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])
                  

                  一些示例输入:

                  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))
                  

                  ...返回此输出:

                  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
                  

                  【讨论】:

                    【解决方案14】:

                    根据需要减去秒,反之亦然,不要称之为时间;有一个同名的包:

                    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
                    

                    【讨论】:

                    • 不太符合要求。
                    【解决方案15】:
                    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}")
                    

                    解释:

                    divmod(x, y) 函数返回(x//y, x%y)

                    day 变量中,x//y 是天数,x%y 是剩余秒数。

                    所以对于hour 变量,day 变量的其余部分是输入。同样,您可以使用这个简单的程序最多计算一周。

                    【讨论】:

                      【解决方案16】:

                      上面声明 divmod 更慢的“timeit”答案存在严重的逻辑缺陷。

                      Test1 调用运算符。

                      Test2 调用函数 divmod, 并且调用函数有开销。

                      更准确的测试方法是:

                      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 更快。

                      【讨论】:

                        【解决方案17】:

                        补丁以及Ralph Bolton's answer。移动到一个类并将 tulp 的 tulp(间隔)移动到字典。根据粒度添加可选的舍入函数(默认启用)。准备使用 gettext 进行翻译(默认为禁用)。这是打算从模块加载的。这是针对 python3(测试 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
                        

                        这是课程:

                        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))
                        

                        使用它:

                        myformater = FormatTimestamp()
                        myconverter = myformater.convert(seconds) 
                        

                        粒度 = 1 - 5,四舍五入 = True / False,平移 = True / False

                        一些测试来显示差异:

                        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()
                        
                        秒数:131440
                            Full - 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
                        
                        秒数:563440
                            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
                        
                        秒数: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
                        
                        秒数: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
                        
                        秒: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
                        

                        我准备好了法语翻译。但是翻译速度很快……就几个字。 希望这会有所帮助,因为其他答案对我有很大帮助。

                        【讨论】:

                          【解决方案18】:

                          这就像Bolton 的答案,但有一些补充......

                          • 将比率存储在字典而不是元组中以提高可读性。
                          • 添加了一个 if 检查 0 秒输入。
                          • 添加了一个 if 检查以将最后一个 , 更改为 and 以获得完整的语法。
                          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
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2012-01-06
                            • 1970-01-01
                            • 2012-09-27
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多