【问题标题】:MYSQL Date Time Round To Nearest HourMYSQL 日期时间四舍五入到最近的时间
【发布时间】:2012-03-29 14:59:02
【问题描述】:

我在 MySQL 数据库中有一个日期时间字段,并希望将结果输出到最接近的时间。

例如2012-04-01 00:00:01 应改为 2012-04-01 00:00:00

【问题讨论】:

标签: mysql datetime


【解决方案1】:

更新:我认为https://stackoverflow.com/a/21330407/480943 是一个更好的答案。


你可以用一些日期算术来做到这一点:

SELECT some_columns,
    DATE_ADD(
        DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00"),
        INTERVAL IF(MINUTE(the_date) < 30, 0, 1) HOUR
    ) AS the_rounded_date
FROM your_table

解释:

  • DATE_FORMAT:DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") 返回截断到最接近小时的日期(将分钟和秒部分设置为零)。

  • MINUTE:MINUTE(the_date)获取日期的分钟值。

  • IF:这是有条件的;如果参数1中的值为真,则返回参数2,否则返回参数3。所以IF(MINUTE(the_date) &lt; 30, 0, 1)的意思是“如果分钟值小于30,则返回0,否则返回1”。这就是我们要用来四舍五入的——它是要重新添加的小时数。

  • DATE_ADD:这会将回合的小时数添加到结果中。

【讨论】:

    【解决方案2】:

    半小时是 30 分钟。只需将 30 分钟添加到时间戳并截断分钟和秒。

    SELECT DATE_FORMAT(DATE_ADD(timestamp_column, INTERVAL 30 MINUTE),'%Y-%m-%d %H:00:00') FROM table

    【讨论】:

      【解决方案3】:

      soul 的第一个解决方案是截断而不是舍入,第二个解决方案不适用于夏令时情况,例如:

      select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300));
      

      这是另一种方法(1):

      DATE_ADD(
          tick,
          INTERVAL (IF((MINUTE(tick)*60)+SECOND(tick) < 1800, 0, 3600) - (MINUTE(tick)*60)+SECOND(tick)) SECOND
      )
      

      如果你不需要担心秒,你可以像这样简化它(2):

      DATE_ADD(
          tick,
          INTERVAL (IF(MINUTE(tick) < 30, 0, 60) - MINUTE(tick)) MINUTE
      )
      

      或者如果你喜欢截断而不是舍入,这里是灵魂方法(3)的更简单版本:

      DATE_SUB(tick, INTERVAL MINUTE(tick)*60+SECOND(tick) SECOND)
      

      编辑:我在本地机器上分析了其中一些查询,发现 100,000 行的平均时间如下:

      • soul 的 UNIXTIME 方法:0.0423 毫秒(快,但不适用于 DST)
      • 我的方法 3:0.1255 毫秒
      • 我的方法 2:0.1289 毫秒
      • Ben Lee 的 DATE_FORMAT 方法:0.1495 毫秒
      • 我的方法1:0.1506 ms

      【讨论】:

      • 打勾因为我只是想截断
      • DATE_FORMAT 很慢?我从来没有听说过。您对此有参考/基准吗?我在谷歌上找不到任何关于 DATE_FORMAT 性能不佳的信息,也没有任何迹象表明对 MINUTE()SECOND() 的调用会比对 DATE_FORMAT 的调用快得多。在任何情况下,任何性能差异不应该是纳秒级的——对于几乎所有现实世界的目的来说基本上是不可见/可以忽略不计的?
      • @BenLee 我预计操作字符串和解析日期会比MINUTE/SECOND 慢得多,但在分析了这两种情况之后,情况并非如此。你的解决方案甚至可能比我的要快一点(可能是因为我两次调用MINUTESECOND?)。但是,我省略秒的示例比DATE_FORMAT 快。我会更新我的答案。
      • 对于其他人的信息,截断到其他分钟间隔(例如 15 分钟):选择 timestamp,date_sub(timestamp,interval (minute(timestamp) % 15)* 60 +second(timestamp) second)...
      【解决方案4】:

      来自How to round a DateTime in MySQL?

      当您使用日期时间数据类型时,这有点令人讨厌;存储函数的理想候选者。

      DATE_SUB(DATE_SUB(time, INTERVAL MOD(MINUTE(time),5) MINUTE ), 
               INTERVAL SECOND(time) SECOND)
      

      使用 UNIXTIME 时间戳会更容易,但仅限于 1970 - 2038 日期范围。

      FROM_UNIXTIME(UNIX_TIMESTAMP(time) - MOD(UNIX_TIMESTAMP(time),300))
      

      祝你好运。

      【讨论】:

      • 小心这个。对于介于夏令时更改之间的日期时间,unix 时间方法失败。例如:select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300));
      【解决方案5】:

      要向下舍入到当前小时,请选择:

      FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(column_name) / 3600) * 3600).

      值以当前时区表示doc

      【讨论】:

        【解决方案6】:

        这将返回下一个小时,即'2012-01-02 18:02:30'将转换为'2012-01-02 19:00:00'

        TIMESTAMPADD(HOUR,
            TIMESTAMPDIFF(HOUR,CURDATE(),timestamp_column_name),
            CURDATE())
        

        您可以使用任意日期来代替CURDATE(),例如'2000-01-01' 如果系统日期在两次调用函数之间发生变化,不确定使用CURDATE()是否会出现问题,不知道Mysql是否会同时调用这两个函数。

        获得最近的小时是:

        TIMESTAMPADD(MINUTE,
            ROUND(TIMESTAMPDIFF(MINUTE,CURDATE(),timestamp_column_name)/60)*60,
            CURDATE())
        

        将 60 更改为 15 将获得最近的 15 分钟间隔,使用 SECOND 可以获得最接近的所需秒间隔,等等。

        要获取前一小时的信息,请使用 TRUNCATE()FLOOR() 而不是 ROUND()

        希望这会有所帮助。

        【讨论】:

          【解决方案7】:

          如果您需要将时间四舍五入到下一个小时,您可以使用这个:

          SELECT TIME_FORMAT(
            ADDTIME(
              TIMEDIFF('16:15', '10:00'), '00:59:00'
            ),
            '%H:00:00'
          )
          

          【讨论】:

            【解决方案8】:

            我认为这是最好的方法,因为它也将使用最少的资源-

            date_add(date(date_completed), interval hour(date_completed) hour) as date_hr
            

            【讨论】:

              猜你喜欢
              • 2015-02-04
              • 1970-01-01
              • 2021-12-15
              • 2022-01-02
              • 1970-01-01
              • 2021-12-16
              • 1970-01-01
              • 1970-01-01
              • 2013-10-17
              相关资源
              最近更新 更多