Конвертиране на времето за дата в Unix timestamp и обратно в python

Имам dt = datetime(2013,9,1,11) и искам да получа Unix времева марка на този обект datetime.

Когато направя (dt - datetime(1970,1,1)).total_seconds(), получавам времевия печат 1378033200.

Когато го преобразувам обратно с помощта на datetime.fromtimestamp, получавам datetime.datetime(2013, 9, 1, 6, 0).

Часът не съвпада. Какво съм пропуснал тук?

Решение

Това, което сте пропуснали тук, са часовите зони.

Предполага се, че сте се отклонили с пет часа от UTC, така че 2013-09-01T11:00:00 местно време и 2013-09-01T06:00:00Z са едно и също време.

Трябва да прочетете горната част на документацията datetime, където се обяснява за часовите зони и "наивни" и "осъзнати" обекти.

Ако първоначалното ви наивно време за дата е било UTC, начинът да го възстановите е да използвате utcfromtimestamp вместо fromtimestamp.

От друга страна, ако оригиналното ви наивно време за дата е било локално, не би трябвало да изваждате UTC времеви печат от него на първо място; вместо това използвайте datetime.fromtimestamp(0).

Ако пък сте имали обект с осъзнато datetime, трябва или да използвате локална (осъзната) епоха и от двете страни, или изрично да конвертирате към и от UTC.

Ако имате или можете да преминете към Python 3.3 или по-нова версия, можете да избегнете всички тези проблеми, като просто използвате метода timestamp, вместо да се опитвате да разберете как да го направите сами. А дори и да нямате, може да помислите за заемане на изходния му код.

(А ако можете да изчакате Python 3.4, изглежда, че PEP 341 вероятно ще влезе в окончателната версия, което означава, че всички неща, за които говорихме с J.F. Sebastian в коментарите, би трябвало да могат да се правят само със stdlib и да работят по един и същи начин както на Unix, така и на Windows.)

Коментари (9)

Вместо този израз за създаване на POSIX времева марка от dt,

(dt - datetime(1970,1,1)).total_seconds()

Използвайте това:

int(dt.strftime("%s"))

Получавам правилния отговор във вашия пример, като използвам втория метод.

EDIT: Някои допълнителни действия... След някои коментари (вижте по-долу), бях любопитен за липсата на поддръжка или документация за %s в strftime. Ето какво намерих:

В Python source за datetime и time, низът STRFTIME_FORMAT_CODES ни казва:

"Other codes may be available on your platform.
 See documentation for the C library strftime function."

Така че сега, ако man strftime (на BSD системи като Mac OS X), ще намерите поддръжка за %s:

"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."

Така или иначе, ето защо %s работи на системите, на които работи. Но има и по-добри решения на проблема на OP'а (които отчитат часовите зони). Виж приетия отговор на @abarnert'тук.

Коментари (9)

Когато конвертира към unix timestamp, питонът основно приема UTC, но при обратното конвертиране ще ви даде дата, конвертирана към местния часови пояс.

Вижте този въпрос/отговор; https://stackoverflow.com/questions/18812638/get-timezone-used-by-datetime-datetime-fromtimestamp

Коментари (0)