Mysql
 sql >> Database >  >> RDS >> Mysql

Perché l'impostazione del fuso orario di Django ha effetto sull'epoca?

Non sono un guru di Python o Django, quindi forse qualcuno può rispondere meglio di me. Ma ci proverò comunque.

Hai detto che lo stavi archiviando in un DateTimeField di Django , che secondo i documenti a cui hai fatto riferimento , lo memorizza come datetime Python .

Guardando i documenti per datetime , penso che la chiave sia capire la differenza tra valori "ingenuo" e "consapevole".

E poi facendo ulteriori ricerche, mi sono imbattuto in questo eccellente riferimento . Assicurati di leggere la seconda sezione, "Oggetti datetime ingenui e consapevoli". Questo dà un po' di contesto a quanto di questo è controllato da Django. Fondamentalmente, impostando USE_TZ = true , stai chiedendo a Django di usare aware datetimes invece di ingenuo quelli.

Quindi ho guardato indietro alla tua domanda. Hai detto che stavi facendo quanto segue:

dt = datetime.fromtimestamp(secs)
dt = dt.replace(tzinfo=utc)

Guardando il fromtimestamp documentazione della funzione, ho trovato questo pezzo di testo:

Quindi penso che potresti farlo:

dt = datetime.fromtimestamp(secs, tz=utc)

Poi di nuovo, proprio sotto quella funzione, i documenti mostrano utcfromtimestamp funzione, quindi forse dovrebbe essere:

dt = datetime.utcfromtimestamp(secs)

Non so abbastanza su Python per sapere se sono equivalenti o meno, ma potresti provare a vedere se uno dei due fa la differenza.

Speriamo che uno di questi faccia la differenza. In caso contrario, per favore fatemelo sapere. Conosco molto bene la data e l'ora in JavaScript e in .Net, ma sono sempre interessato a come queste sfumature si comportano in modo diverso in altre piattaforme, come Python.

Aggiorna

Per quanto riguarda la parte MySQL della domanda, dai un'occhiata a questo violino .

CREATE TABLE foo (`date` DATETIME);
INSERT INTO foo (`date`) VALUES (FROM_UNIXTIME(1371131402));

SET TIME_ZONE="+00:00";
select `date`, UNIX_TIMESTAMP(`date`) from foo;

SET TIME_ZONE="+01:00";
select `date`, UNIX_TIMESTAMP(`date`) from foo;

Risultati:

DATE                           UNIX_TIMESTAMP(`DATE`)
June, 13 2013 13:50:02+0000    1371131402
June, 13 2013 13:50:02+0000    1371127802

Sembrerebbe che il comportamento di UNIX_TIMESTAMP La funzione è infatti influenzata da MySQL TIME_ZONE ambientazione. Non è così sorprendente, dal momento che è nella documentazione. Ciò che sorprende è che l'output della stringa di datetime ha lo stesso valore UTC indipendentemente dall'impostazione.

Ecco cosa penso stia succedendo. Nei documenti per UNIX_TIMESTAMP funzione, dice:

Nota che non dice che può essere un DATETIME - dice che può essere un DATETIME stringa . Quindi penso che il valore effettivo venga convertito implicitamente in una stringa prima di essere passato alla funzione.

Quindi ora guarda questo violino aggiornato che converte in modo esplicito.

SET TIME_ZONE="+00:00";
select `date`, convert(`date`, char), UNIX_TIMESTAMP(convert(`date`, char)) from foo;

SET TIME_ZONE="+01:00";
select `date`, convert(`date`, char), UNIX_TIMESTAMP(convert(`date`, char)) from foo;

Risultati:

DATE                           CONVERT(`DATE`, CHAR)  UNIX_TIMESTAMP(CONVERT(`DATE`, CHAR))
June, 13 2013 13:50:02+0000    2013-06-13 13:50:02    1371131402
June, 13 2013 13:50:02+0000    2013-06-13 13:50:02    1371127802

Puoi vedere che quando si converte in dati di carattere, rimuove l'offset. Quindi, ovviamente, ora ha senso che quando UNIX_TIMESTAMP prende questo valore come input, assume l'impostazione del fuso orario locale e quindi ottiene un timestamp UTC diverso.

Non sono sicuro se questo ti aiuterà o meno. Devi approfondire esattamente come Django chiama MySQL sia per la lettura che per la scrittura. Utilizza effettivamente il UNIX_TIMESTAMP funzione? O era solo quello che hai fatto durante i test?