2012-03-13 33 views
28

Ho un campo di data e ora in un database MySQL e desidero inviare il risultato all'ora più vicina.MYSQL Data Arrotonda all'ora più vicina

ad es. 2012-04-01 00:00:01 dovrebbe leggere 2012-04-01 00:00:00

+0

possibile duplicato di [Come per arrotondare un DateTime in MySQL?] (Http: // StackOverflow. it/questions/1921362/how-to-round-a-datetime-in-mysql) – Makoto

risposta

5

Da How to round a DateTime in MySQL?:

E 'un po' brutto quando lo si fa con i tipi di dati datetime; un buon candidato per una funzione memorizzata.

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

è più facile quando si utilizza timestamp unixtime ma questo è limitato a un 1970 - 2038 intervallo di date.

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

Buona fortuna.

+1

Stai attento a questo.L'approccio di tempo unix non riesce per gli intervalli di tempo compresi tra le modifiche all'ora legale. Ad esempio: 'seleziona FROM_UNIXTIME (UNIX_TIMESTAMP ('2012-03-11 2:14:00') - MOD (UNIX_TIMESTAMP ('2012-03-11 2:14:00'), 300));' –

36

Aggiornamento: Penso che https://stackoverflow.com/a/21330407/480943 sia una risposta migliore.


Puoi farlo con una certa data l'aritmetica:

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 

Spiegazioni:

  • DATE_FORMAT: DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") restituisce la data troncato verso il basso per l'ora più vicina (imposta minuto e parti secondarie a zero).

  • MINUTE: MINUTE(the_date) ottiene il valore minuto della data.

  • IF: Questo è un condizionale; se il valore nel parametro 1 è true, restituisce il parametro 2, altrimenti restituisce il parametro 3. Quindi IF(MINUTE(the_date) < 30, 0, 1) significa "Se il valore del minuto è inferiore a 30, restituisce 0, altrimenti restituisce 1". Questo è ciò che useremo per arrotondare: è il numero di ore da aggiungere.

  • DATE_ADD: questo aggiunge il numero di ore per il round al risultato.prima soluzione

12

dell'anima tronca invece di arrotondamento e la seconda soluzione non funziona con casi all'ora legale quali:

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

Ecco un metodo alternativo (1):

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

Se non ti devi preoccupare di secondi puoi semplificarlo in questo modo (2):

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

O se preferite troncare invece di turno, qui è la versione più semplice del metodo di anima (3):

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

EDIT: ho fatto il profilo alcune di queste domande sulla mia macchina locale e ha scoperto che per 100.000 righe le tempi medi sono stati i seguenti:

  • UNIXTIME metodo dell'anima: 0,0423 ms (veloce, ma non funziona con l'ora legale)
  • mio metodo 3: 0.1255 ms
  • mio metodo 2: 0.1289 Metodo DATE_FORMAT di ms
  • Ben Lee: 0.1495 ms
  • mio metodo 1: 0.1506 ms
+0

Seleziona da me perché volevo solo troncare – MikeKulls

+0

'DATE_FORMAT' è lento? Non ne ho mai sentito parlare. Hai un riferimento/benchmark per questo? Non riesco a trovare nulla su google riguardo a "DATE_FORMAT" con prestazioni scadenti, e nulla indica che le chiamate a 'MINUTE()' e 'SECOND()' sarebbero significativamente più veloci di una chiamata a 'DATE_FORMAT'. In ogni caso, la differenza di prestazioni non dovrebbe essere al livello di magnitudine nanosecondo - essenzialmente invisibile/trascurabile per quasi tutti gli scopi del mondo reale? –

+0

@BenLee Mi aspettavo che la manipolazione delle stringhe e l'analisi delle date sarebbero state molto più lente di 'MINUTE' /' SECOND', ma dopo aver profilato i due casi che non erano veri. La tua soluzione è anche potenzialmente un po 'più veloce della mia (forse a causa della mia chiamata 'MINUTE' e' SECOND' due volte?). Tuttavia, il mio esempio che omette i secondi è più veloce di 'DATE_FORMAT'. Aggiornerò la mia risposta –

1

Ciò restituirà l'ora successiva, che è '2012-01-02 18:02:30' sarà convertito in '2012-01-02 19:00:00'

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

Invece di CURDATE() è possibile utilizzare una data arbitraria, ad esempio '2000-01-01' Non sono sicuro se ci potrebbero essere problemi usando CURDATE() se il sistema data cambia tra le due chiamate alla funzione, non so se Mysql chiamerebbe entrambe allo stesso tempo.

per ottenere il vicina ore sarebbero date:

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

cambiando 60 da 15 otterrebbe l'approssimazione intervallo di 15 minuti, utilizzando secondo si può ottenere il più vicino secondo intervallo desiderato, ecc

Per ottenere l'ora precedente utilizzare TRUNCATE() o FLOOR() anziché ROUND().

Spero che questo aiuti.

20

La metà dell'ora è di 30 minuti. Basta aggiungere 30 minuti al timestamp e troncare minuti e secondi.

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

0

Se avete bisogno di arrotondare appena il tempo di un'ora è possibile utilizzare questo:

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