【问题标题】:Rounding up to nearest 30 minutes in python在python中四舍五入到最近的30分钟
【发布时间】:2015-12-19 19:14:33
【问题描述】:

我有下面的代码。

我想将 TIME 舍入到一小时中最接近的 30 分钟。例如:12:00PM 或 12:30PM 等。

EASTERN_NOW = timezone.localtime(timezone.now() + timedelta(minutes=30))

TIME = datetime.time(EASTERN_NOW.time().hour, EASTERN_NOW.time().minute).strftime(
    VALID_TIME_FORMATS[2])

提前致谢

【问题讨论】:

    标签: python time


    【解决方案1】:

    向上四舍五入到最接近的 30 分钟:

    #!/usr/bin/env python3
    from datetime import datetime, timedelta
    
    def ceil_dt(dt, delta):
        return dt + (datetime.min - dt) % delta
    
    now = datetime.now()
    print(now)    
    print(ceil_dt(now, timedelta(minutes=30)))
    

    The formula is suggested by @Mark Dickinson (for a different question).

    输出

    2015-09-22 19:08:34.839915
    2015-09-22 19:30:00
    

    注意:如果输入是时区感知日期时间对象,例如 EASTERN_NOW 在您的情况下,如果您想保留四舍五入的本地时间并附加正确的 tzinfo,则应调用 timezone.make_aware(rounded_dt.replace(tzinfo=None)),否则您可能会出错如果舍入跨越 DST 边界,则为时区信息。或者为避免因本地时间不明确而失败,请手动调用.localize()

    localize = getattr(rounded_dt.tzinfo, 'localize', None)
    if localize:
       rounded_dt = localize(rounded_dt.replace(tzinfo=None),
                             is_dst=bool(rounded_dt.dst()))
    

    【讨论】:

    • 我收到TypeError: unsupported operand type(s) for %: 'datetime.timedelta' and 'datetime.timedelta'
    • @dan-klasson 注意:脚本中的python3 shebang
    • 任何 Python 2.x 等价物?
    • @Rainymood:单击答案中的链接并查看其他答案(想法是将 timedelta 转换为秒:在这种情况下为 1800)。看看有没有replacing 900 with 1800 works
    【解决方案2】:

    你可以使用向前四舍五入:

    #!/usr/bin/env python3
    from datetime import datetime, timedelta
    
    def ceil_dt(dt, delta):
        return dt + (datetime.min - dt) % delta
    
    now = datetime.now()
    print(now)    
    print(ceil_dt(now, timedelta(minutes=30)))
    

    四舍五入到最接近的第 30 分钟

    def rounded_to_the_last_30th_minute_epoch():
        now = datetime.now()
        rounded = now - (now - datetime.min) % timedelta(minutes=30)
        return rounded
    

    【讨论】:

      【解决方案3】:

      您可以将分钟数除以 30,然后将其四舍五入,然后再乘以 30,得到 0、30 或 60 分钟:

      date = datetime.datetime(2015, 9, 22, 12, 35)
      approx = round(date.minute/30.0) * 30
      
      date = date.replace(minute=0)
      date += datetime.timedelta(seconds=approx * 60)
      time = date.time()
      print(time.strftime('%H:%M'))
      # prints '13:30'
      

      我正在使用 datetime 对象,因为 timedelta 不适用于时间对象。最后你可以使用date.time()获取时间。

      【讨论】:

      • 太棒了..你知道如何四舍五入到最接近的 10 或 20 分钟吗..
      • @Azam 同样的方式。你将你的分钟数除以 10,去掉余数,然后乘以 10。所以 36 分钟首先是 3.6,然后你去掉小数部分(或使用只留下整数的整数除法),然后乘以 10 -> 30 . 一样的20分钟。 36 / 20 -> 1.8,去掉留下 1 的小数部分,乘以 20 -> 20 分钟
      【解决方案4】:

      您可以将日期时间输入分开并调整时间

       def ajustTime():
      
      from datetime import datetime
      
      mytime= datetime.now().strftime("%Y-%m-%d %H-%M")
      
      m = mytime.split()
      
      hours, mints = m[1].split('-')
      
      if 15 <= int(mints) <= 45:
          mints = ':30'
      elif int(mints) < 15:
          mints = ':00'
      elif int(mints) > 45:
          mints = ':00'
          h = int(hours) + 1
          hours = str(h)
      
      print(m[0] + " " + hours + mints)
      

      调整时间()

      输出

      2015-09-22 15:42:03.587633

      2015-09-22 15:30

      2015-09-22 15:46:01.956860

      2015-09-22 16:00

      【讨论】:

        【解决方案5】:
        >>> from dateutil.rrule import rrule, MINUTELY
        >>> import datetime
        >>> import bisect
        >>> times = list(rrule(MINUTELY,interval=30,dtstart=datetime.date.today(),count=
        48))
        >>> print times[bisect.bisect(times,datetime.datetime.now())]
        2015-09-22 11:00:00
        >>>
        

        请注意,此解决方案使用了可以使用pip install dateutil 安装的第三方dateutil 库...当然,您可以不使用它来解决它...但是使用它会更容易。

        【讨论】:

        • 感谢 Joran 会尝试并通知您。
        • Joran 它有效,但我正在寻找的是,如果它的 1:15 或 1:17 时间应该显示为 1:30 而不是 1:15 或 1 前 30 分钟: 17.
        • 它确实应该四舍五入到最近的 :30 或 :00(在它之前的位置)......你试过这个吗?
        • 很好,它确实有效。我现在只是想在我的时区以“04:30 PM”的格式获取它。
        • 什么意思?没关系,我在阅读其他答案后明白了。 :P
        【解决方案6】:

        向下取整

        • 从您想要取整的时间中提取分钟
        • 使用地板除法,找到当前小时的整数间隔(从当前分钟的地板除法和时间间隔,即要向下舍入的间隔)。
        • 将时间间隔乘以整数,得到四舍五入的分钟数
        • 使用 .replace() 将分钟更改为向下舍入的分钟(秒和毫秒为零)。

        或者,换句话说,使用当前分钟内的整个间隔(x)的数量,将分钟替换为间隔的数量(x *间隔):

        #!/usr/bin/env python3
        def floor_dt(dt, interval):
            replace = (dt.minute // interval)*interval
            return dt.replace(minute = replace, second=0, microsecond=0)
        
        print(datetime.now())
        # datetime.datetime(2019, 5, 30, 22, 25, 31, 115901)
        print(floor_dt(datetime.now(),30))
        # datetime.datetime(2019, 5, 30, 22, 0)
        
        print(datetime.now())
        # datetime.datetime(2019, 5, 30, 22, 26, 29, 469555)
        print(floor_dt(datetime.now(),10))
        # datetime.datetime(2019, 5, 30, 22, 20)
        

        【讨论】:

          【解决方案7】:

          要向下和向上取整,您可以使用这两个函数。您无需计算秒数或使用数学模块。

          from datetime import timedelta, datetime
          
          def ceil_date(date, **kwargs):
              secs = timedelta(**kwargs).total_seconds()
              return datetime.fromtimestamp(date.timestamp() + secs - date.timestamp() % secs)
          
          def floor_date(date, **kwargs):
              secs = timedelta(**kwargs).total_seconds()
              return datetime.fromtimestamp(date.timestamp() - date.timestamp() % secs)
          
          

          用法类似于timedelta,因为通过了kwargs

          now = datetime.now() #15:12:12
          
          ceil_date(now, minutes=5) #15:15:00
          floor_date(now, minutes=5) #15:10:00
          

          【讨论】:

            【解决方案8】:

            这应该也可以,但不确定时区

            rounded=time.gmtime(30*60*(round(time.time()/(30*60))))
            

            【讨论】:

              【解决方案9】:

              感谢所有提供意见的人。我用自己的方法解决了这个问题。

              min_time = timezone.localtime(timezone.now())
              min_time_est = min_time.minute 
              if min_time_est > 30:
                  add_mins = 60 - min_time_est
              else:
                  add_mins = 30 - min_time_est
              
              EASTERN_NOW = timezone.localtime(timezone.now() + timedelta(minutes=add_mins))
              TIME = datetime.time(EASTERN_NOW.time().hour, EASTERN_NOW.time().minute).strftime(
                  VALID_TIME_FORMATS[2])
              

              如果其他人有类似的问题。 about 'TIME' 每 30 分钟输出一次,例如 '1:00PM' 或 '1:30PM'。

              【讨论】:

              • 使用add_mins = -min_time.minute % 30(如果.minute==0,您的代码会不必要地跳过30分钟)。如果当前时区的 utc 偏移量的更改未与 30 分钟对齐 (my answer calls localize() to keep the time while getting the correct tzinfo),您的代码可能会失败
              • 使用eastern_now.strftime(valid_time_format)(无需调用eastern_now.time(),无需再次构造datetime.time())。
              【解决方案10】:

              在不使用第三方库和几行代码的情况下,通过round_mins 以分钟为单位向上取整。

              import datetime
              round_mins = 30
              now = datetime.datetime.now()
              mins = now.minute - (now.minute % round_mins)
              print datetime.datetime(now.year, now.month, now.day, now.hour, mins) + datetime.timedelta(minutes=round_mins)
              

              【讨论】:

              • 请提供一些解释。对于以后遇到同样问题的人来说,纯代码的答案通常没有那么有帮助。
              猜你喜欢
              • 1970-01-01
              • 2013-07-15
              • 2017-12-02
              • 2010-10-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多