2012-03-13 18 views
28

Tengo un campo de fecha y hora en una base de datos MySQL y deseo enviar el resultado a la hora más cercana.MYSQL Fecha Hora Ronda a la hora más cercana

p. Ej. 2012-04-01 00:00:01 debe leer 2012-04-01 00:00:00

+0

posible duplicado de [Cómo redondear un DateTime en MySQL?] (Http: // stackoverflow. com/questions/1921362/how-to-round-a-datetime-in-mysql) – Makoto

Respuesta

5

De How to round a DateTime in MySQL?:

Es un poco desagradable cuando lo haces con los tipos de datos de fecha y hora; un buen candidato para una función almacenada.

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

Es más fácil cuando utiliza marcas de tiempo UNIXTIME pero está limitado a un intervalo de fechas 1970 - 2038.

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

Buena suerte.

+1

Tenga cuidado con esto.El enfoque del tiempo Unix falla para las fechas que caen entre los cambios de horario de verano. Por ejemplo: 'seleccione FROM_UNIXTIME (UNIX_TIMESTAMP ('2012-03-11 2:14:00') - MOD (UNIX_TIMESTAMP ('2012-03-11 2:14:00'), 300));' –

36

Actualización: Creo que https://stackoverflow.com/a/21330407/480943 es una mejor respuesta.


Puede hacerlo con un poco de aritmética de fechas:

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 

explicaciones:

  • DATE_FORMAT: DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") devuelve la fecha truncado hasta la hora más cercana (fija la hora y segundas partes a cero).

  • MINUTE: MINUTE(the_date) obtiene el valor de minutos de la fecha.

  • IF: Este es un condicional; si el valor del parámetro 1 es verdadero, devuelve el parámetro 2; de lo contrario, devuelve el parámetro 3. Entonces IF(MINUTE(the_date) < 30, 0, 1) significa "Si el valor de los minutos es menor que 30, devuelva 0, de lo contrario devuelva 1". Esto es lo que vamos a utilizar para redondear: es el número de horas para volver a agregar.

  • DATE_ADD: Esto agrega el número de horas de la ronda en el resultado.primera solución

12

de alma trunca en lugar de redondeo y la segunda solución no funciona con los casos de ahorro de luz tales como:

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

Aquí es un método alternativo (1):

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

Si no necesita preocuparse por los segundos, puede simplificarlo así (2):

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

O si lo prefiere para truncar en lugar de redonda, aquí es la versión más simple del método de alma (3):

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

EDIT: perfilado algunas de estas consultas en mi máquina local y encontró que para los 100.000 filas las tiempos medios fueron los siguientes:

  • UNIXTIME método del alma: 0,0423 ms (rápido, pero no funciona con el horario de verano)
  • mi método 3: 0.1255 ms
  • mi método 2: 0.1289 DATE_FORMAT método de ms
  • Ben Lee: 0.1495 ms
  • mi método 1: 0.1506 ms
+0

Marque de porque yo solo quería truncar – MikeKulls

+0

'DATE_FORMAT' es lento? Nunca había escuchado acerca de eso. ¿Tiene una referencia/punto de referencia para eso? No puedo encontrar nada en Google sobre 'DATE_FORMAT' que tenga un rendimiento deficiente, y nada que indique que las llamadas a' MINUTE() 'y' SECOND() 'serían significativamente más rápidas que una llamada a' DATE_FORMAT'. En cualquier caso, ¿no debería haber alguna diferencia de rendimiento en el nivel de magnitud de nanosegundos, esencialmente invisible/insignificante para casi todos los propósitos del mundo real? –

+0

@BenLee. Esperaba que manipular cadenas de caracteres y analizar las fechas fuera mucho más lento que 'MINUTE '/' SEGUNDO ', pero después de perfilar los dos casos, eso no es cierto. Su solución es incluso potencialmente un poco más rápida que la mía (¿quizás debido a que la mina llamó 'MINUTE' y' SECOND' dos veces?). Sin embargo, mi ejemplo que omite los segundos es más rápido que 'DATE_FORMAT'. Actualizaré mi respuesta. –

1

Esto devolverá la hora siguiente, que se '2012-01-02 18:02:30' se convertirá en '2012-01-02 19:00:00'

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

En lugar de CURDATE() puede usar una fecha arbitraria, por ejemplo '2000-01-01' No estoy seguro de si podría haber problemas al usar CURDATE() si el sistema la fecha cambia entre las dos llamadas a la función, no sé si Mysql llamará a ambas al mismo tiempo.

para obtener el hora más cercana sería:

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

cambio de 60 por 15 obtendría el intervalo de 15 minutos más cercano, mediante SEGUNDO puede obtener el segundo intervalo deseado más cercano, etc.

Para obtener la hora anterior, use TRUNCATE() o FLOOR() en lugar de ROUND().

Espero que esto ayude.

20

La mitad de la hora es de 30 minutos. Simplemente agregue 30 minutos a la marca de tiempo y trunque los minutos y segundos.

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

0

Si necesita redondear el tiempo justo para la próxima hora se puede usar esto:

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