2010-05-07 11 views
13

Non è un titolo molto buono, quindi mi scuso.Conversione di una stringa di data precedente al 1970 in un timestamp in MySQL

Per qualche motivo, (non ero la persona che l'ha fatto, ho divagato) abbiamo una struttura di tabella in cui il tipo di campo per una data è varchar. (dispari).

Abbiamo alcune date, come ad esempio:

1932-04-01 00:00:00 and 1929-07-04 00:00:00 

ho bisogno di fare una query che converte queste stringhe di data in un unix ora, però, in MySQL se si converte una data che è prima del 1970 restituirà 0.

Qualche idea?

Grazie mille!

MODIFICA: formato data errato. ooops.

+0

Inoltre, se converto una data prima del 1970 in un timestamp, dovrei aspettarmi un valore negativo. – Flukey

+0

Perché un timestamp unix? Investirei un po 'di tempo per capire se è possibile usare qualcos'altro rispetto ai timestamp unix - come trattare i timestamp unix <1970 in una grande lattina di worm .. – nos

+0

@nos - Sono d'accordo con te interamente, però, ahimè, non è il mio lavoro per farlo. È una di quelle cose in cui un collega mi è venuto incontro per chiedermi se potevo aiutarlo con un problema. Ho raccomandato di cambiarlo, ma è tutto per lui. – Flukey

risposta

17

Aha! Abbiamo trovato una soluzione!

L'SQL per farlo:

SELECT DATEDIFF(STR_TO_DATE('04-07-1988','%d-%m-%Y'),FROM_UNIXTIME(0))*24*3600 -> 583977600 
SELECT DATEDIFF(STR_TO_DATE('04-07-1968','%d-%m-%Y'),FROM_UNIXTIME(0))*24*3600 -> -47174400 

Questo potrebbe essere utile per riferimenti futuri.

È possibile verificare qui: http://www.onlineconversion.com/unix_time.htm

+0

È indipendente dal server t imezone? – Neil

+0

vedere la mia versione di seguito – TheBelgarion

2

convertire queste stringhe di data in un timbro tempo unix

timestamp Unix tradizionali sono un conteggio numero intero senza segno di secondi dal 1-Gen-1970, pertanto, non può rappresentare qualsiasi data prima.

+1

Può se restituisce un valore negativo. PHP ad esempio può capire un valore di timestamp negativo e convertirlo in una stringa ... – Flukey

2

Nella migliore delle ipotesi si avranno risultati misti a seconda del sistema che si sta utilizzando per rappresentare il timestamp.

Da wikipedia

Ci fu originariamente una certa polemica sulla possibilità che il time_t Unix dovrebbe essere firmato o non firmato. Se non firmato, il suo intervallo in futuro sarà raddoppiato, posticipando l'overflow a 32 bit (di 68 anni). Tuttavia, sarebbe quindi in grado di volte rappresentano prima di 1970. Dennis Ritchie, quando ha chiesto su questo problema , ha detto che non aveva pensato molto profondamente su di esso, ma era del parere che la capacità di rappresentano tutte le volte nella sua vita sarebbe bello. (La nascita di Ritchie, nel 1941, è intorno all'ora di Unix -893 400 000.) Il consenso è per time_t da firmare, e questa è la prassi abituale. La piattaforma di sviluppo software per versione 6 del sistema operativo QNX ha un time_t a 32 bit senza segno, sebbene le versioni precedenti di utilizzino un tipo firmato.

Sembra che MySQL tratta timestamp come un intero senza segno, il che significa che i tempi prima che l'Epoc saranno tutti risolvere a 0.

Stando così le cose, si ha sempre la possibilità di implementare il proprio tipo timestamp unsigned e usalo per i tuoi calcoli.

2

Se è possibile per il tuo problema, puoi spostare tutti i tuoi tempi mysql per, diciamo 100 anni, quindi lavorare con i timestamp regolati o calcolare il valore di timestamp negativo.

Come alcuni hanno già detto, assicurati che il tuo sistema utilizzi 64 bit per rappresentare il timestamp, altrimenti il ​​problema dell'anno 2038.

+0

Ho appena letto e prima ho pensato, che maledetta buona idea! : D e quindi rendiamo conto che stiamo girando su un sistema a 32 bit. :-( Stavo facendo un po 'di googl'ing e apparentemente posso usare date_add per ottenere l'intervallo di secondi tra il 1970 e una data di nascita e quindi meno l'intervallo dal 1970. Spero che abbia un senso Ad esempio, I avere questo al momento: SELEZIONA DATE_ADD ('1970-01-01', intervallo t.testdate secondo) come testdate_timestamp FROM random.test t; Ma, ahimè, questo è quanto ho – Flukey

+0

Don! confondere il 64 bit con l'hardware, forse il tuo sistema può gestirlo, provalo. Inoltre, a seconda delle tue esigenze, puoi usare il database per fare tutta la logica relativa alle date per te, così non devi preoccuparti di questo in PHP per esempio - in PHP si potrebbe semplicemente lavorare con, diciamo anni – zaf

-2

Uso Data invece di timestamp. La data risolverà i tuoi problemi. controllare questo link

4

Ho adattato la soluzione di DATEDIFF per includere anche il tempo e non solo i giorni. L'ho trasformato in una funzione memorizzata, ma puoi semplicemente estrarre la parte SELECT se non vuoi utilizzare le funzioni.

DELIMITER | 
CREATE FUNCTION SIGNED_UNIX_TIMESTAMP (d DATETIME) 
RETURNS BIGINT 
DETERMINISTIC 
    BEGIN 
    DECLARE tz VARCHAR(100); 
    DECLARE ts BIGINT; 
    SET tz = @@time_zone; 
    SET time_zone = '+00:00'; 
    SELECT DATEDIFF(d, FROM_UNIXTIME(0)) * 86400 + 
    TIME_TO_SEC(
     TIMEDIFF(
     d, 
     DATE_ADD(MAKEDATE(YEAR(d), DAYOFYEAR(d)), INTERVAL 0 HOUR) 
    ) 
    ) INTO ts; 
    SET time_zone = tz; 
    return ts; 
    END| 
DELIMITER ; 

-- SELECT UNIX_TIMESTAMP('1900-01-02 03:45:00'); 
-- will return 0 
-- SELECT SIGNED_UNIX_TIMESTAMP('1900-01-02 03:45:00'); 
-- will return -2208888900 
0

Per ottenere il massimo. Gamma +/- saggio utilizzare questa query sul campo del compleanno, nel mio caso "yyyy-mm-dd", ma è possibile modificarlo per le vostre esigenze

select name, (@bday:=STR_TO_DATE(birthday,"%Y-%m-%d")),if(year(@bday)<1970,UNIX_TIMESTAMP(adddate(@bday, interval 68 year))-2145916800,UNIX_TIMESTAMP(@bday)) from people 
0

Non ho provato le soluzioni di cui sopra, ma questo potrebbe nel caso in cui non è possibile recuperare il valore della data dal database MySQL sotto forma di data/ora, quindi è possibile provare questa operazione

SELECT TIMESTAMPDIFF (secondo, FROM_UNIXTIME (0), '1960-01-01 00:00: 00');

Problemi correlati