Перетворіть дату пітону в епоху з розривом


209

У мене є час в UTC, з якого я хочу кількість секунд з епохи.

Я використовую стропінг, щоб перетворити його на кількість секунд. Взявши приклад 1 квітня 2012 року.

>>>datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

1 квітня 2012 року UTC від епохи становить 1333238400, але це вище повертає 1333234800, що відрізняється на 1 годину.

Таким чином, схоже, що цей стрингл враховує мій системний час і десь застосовує зміну часового поясу. Я думав, що дата була чисто наївною?

Як я можу обійти це? Якщо можливо, уникаючи імпорту інших бібліотек, крім стандартних. (У мене є проблеми переносимості).



11
Я єдиний, хто зазначає, що ви використовуєте восьмеричні літери в цифрах?
Монітор риб


3
Новіший Python 3.3+ маєdatetime.datetime.timestamp(datetime.datetime.utcnow())
MarkHu

Відповіді:


389

Якщо ви хочете перетворити час дати пітона в секунди з епохи, ви можете це зробити явно:

>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0

У Python 3.3+ ви можете використовувати timestamp()замість цього:

>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0

Чому не слід використовувати datetime.strftime('%s')

Python насправді не підтримує% s як аргумент для стрипінгу (якщо ви перевірте на http://docs.python.org/library/datetime.html#strWeather-and-strptime-behavior його немає у списку), єдиний тому, що це працює, це тому, що Python передає інформацію до стропінгу вашої системи, який використовує ваш локальний часовий пояс.

>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

7
Я божеволіла, намагаючись з'ясувати, чому я бачу стролінг ("% s") багато, але це не в документах. Дякую вам за це нічого!
Джонатан Ванаско

54
не використовуйте .strftime("%s"): він не підтримується, не є портативним, він може мовчки давати неправильний результат для відомого об'єкта дати, він не працює, якщо введення в UTC (як у питанні), але локальний часовий пояс не UTC
jfs

2
@earthmeLon Ваша дужка в дурках неправильна. У Timedeltas (зроблено відніманням двох дат) є total_seconds, але datetimes - ні.
jleahy

2
Це не працює для мене:AttributeError: 'datetime.timedelta' object has no attribute 'total_seconds'
Майкл

3
@Michael Ця функція нова в Python 2.7, ви повинні використовувати старішу версію. Для версій до 2.7 ви можете це зробити td.seconds + td.days*24*3600. Це відкидає частину мікросекунд.
jleahy

100

У мене були серйозні проблеми з Timezones і подібними. Те, як Python поводиться з усім, що трапляється, досить заплутано (для мене). Здається, все працює нормально за допомогою модуля календаря (див. Посилання 1 , 2 , 3 і 4 ).

>>> import datetime
>>> import calendar
>>> aprilFirst=datetime.datetime(2012, 04, 01, 0, 0)
>>> calendar.timegm(aprilFirst.timetuple())
1333238400

7
+1, оскільки це єдина відповідь, яка працює на вхід у запитання.
jfs

це портативний?
Бенджамінц

1
Це слід позначити як слушну відповідь, оскільки це відповідає проблемі, про яку йдеться. vnice kudos
Leo Prince

2
Це "працює", але зауважте, що питання було зазначено: "У мене час у UTC" Цей метод завжди використовуватиме місцевий часовий пояс системи. Неможливо вказати часовий пояс. Якби aprilFirstв цьому прикладі були «відомі» екземпляри і використовували часовий пояс, відмінний від часового поясу системи, результат був би невірним (часовий пояс втрачається вtimetuple() виклику). Отримати правильну відповідь на "свідомий" час ви можете використовувати awaredt.timestamp()на останній Python 3. Для Python 2 складніше; один із способів - використовувати arrowбібліотеку. arrow.get(awaredt).timestampвийде правильно.
Адам Вільямсон

1
Добре, @AdamWilliamson, але код у прикладі не локалізує datetimeоб'єкт, тож я припустив, що "я маю час у UTC" означав, що в ОП був datetimeоб'єкт, який не знав, який вважався в UTC, для якого він хотів отримати epoch(якщо datetimeтрапилося, що це знає TZ, це може змінити щось). Також майте на увазі, що цій відповіді майже 8 років, і багато чого сталося з тих пір ( arrowбуло випущено, наприклад, 2013 р.)
BorrajaX

35
import time
from datetime import datetime
now = datetime.now()

time.mktime(now.timetuple())

1
це неправильний спосіб запису time.time()( mktime()може вийти з ладу під час переходу DST, поки він time.time()продовжує працювати). І він не відповідає на питання, якщо локальний часовий пояс не є UTC (вхід у запитання - в UTC). Навіть якщо вхідний сигнал буде представляти місцевий час, він mktime()також може не працювати для минулих / майбутніх дат, якщо він не використовує базу даних tz, і якщо локальний часовий пояс може мати різні зміщення ультразвукового періоду протягом років, наприклад, Європа / Москва в 2010-2015 роках - - використовуйте натомість UTC (як у запитанні) або об'єкти дат, що знають часовий пояс.
jfs

тут є більше проблем з перетворенням локального часу (наприклад, повернутого .now()) до часової позначки епохи (повертається mktime()) . Якщо ви його прочитали; Ви розумієте, чому введення UTC (використовується в запитанні) (набагато) краще, ніж наївний об'єкт дати, що представляє місцевий час
jfs

14
import time
from datetime import datetime
now = datetime.now()

# same as above except keeps microseconds
time.mktime(now.timetuple()) + now.microsecond * 1e-6

(Вибачте, це не дозволить мені коментувати існуючу відповідь)


Це тому, що time.mktime не враховує мікросекундну частину, правда?
Едуардо

1
Правильно. У структурі кордону часу (на основі Структури) немає місця для мікросекунд, тому нам потрібно захопити інформацію з об'єкта datetime і додати її в кінці.
Чарльз Плагер


На моїх машинах це працює правильно, навіть якщо мій часовий пояс - ET.
Чарльз Плагер

1
Це дасть вам різні часові позначки для різних систем на основі локального часу системи.
Юсаф

6

якщо вам просто потрібна мітка часу в unix / epoch time, цей один рядок працює:

created_timestamp = int((datetime.datetime.now() - datetime.datetime(1970,1,1)).total_seconds())
>>> created_timestamp
1522942073L

і залежить лише від datetime робіт у python2 та python3


2

Це працює в Python 2 і 3:

>>> import time
>>> import calendar
>>> calendar.timegm(time.gmtime())
1504917998

Дотримуйтесь лише офіційних документів ... https://docs.python.org/2/library/time.html#module-time


1) Це передбачає, що ви хочете перетворити зараз, а не випадковий об'єкт datetime. 2) Вам не потрібен календар. time.mktime (randomDateTime.timetuple ()) + randomDateTime.microsecond * 1e-6
Charles Plager

@CharlesPlager time.mktime невірно; він інтерпретує аргумент у локальному часовому поясі, тоді як ОП хоче, щоб час інтерпретувався у UTC (як це робить Calendar.timegm).
тушканчик

Це найточніша відповідь для мене, якщо ви хочете перетворити свій час в GMT і хочете зберегти його таким чином під час перетворення в часову позначку епохи.
Юсаф

Тільки слідуючи вашої відповіді, Calendar.timegm (datetime.strptime ("2019-05-03T05: 40: 09.770494 + 00: 00" [: 16], '% Y-% m-% dT% H:% M'). timetuple ()) у мене є мітки часу МСВ і незалежно від того , яку систему ви працювати на ньому дає мені правильну мітку часу, трюк полягає в використанні strptime.timetumple
Yousaf

2

Для явного незалежного від часового поясу рішення використовуйте бібліотеку pytz.

import datetime
import pytz

pytz.utc.localize(datetime.datetime(2012,4,1,0,0), is_dst=False).timestamp()

Вихід (поплавок): 1333238400.0


побачив подібну відповідь на stackoverflow.com/a/21145908/4355695 , але цей як однолінійний відмінно підходить для мого використання, коли вхідні дані знаходяться в UTC та просто .timestamp () передбачав, що це буде за місцевим часом .
Nikhil VJ

Це працює на дати менше 1970 року. Дякую. Прийнята відповідь не працює на дати менше 1970 року. (Python 3.7.3 64-розрядний Anaconda3)
canbax

-1

У Python 3.7

Поверніть час дати, що відповідає датовому рядку, в одному з форматів, що випускаються date.isoformat () та datetime.isoformat (). Зокрема, ця функція підтримує рядки у форматі (іх) YYYY-MM-DD [* HH [: MM [: SS [.fff [fff]]]] [+ HH: MM [: SS [.ffffff]]]] , де * може відповідати будь-якому одному символу.

https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat


1
Майте на увазі, що це було введено в Python 3.7.
keithpjolley
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.