Из часового пояса и времени UTC получите разницу в секундах по местному времени в этот момент времени

Это должно быть очень просто, но я не могу понять это на Python. Я хочу иметь функцию, которая принимает два аргумента, время UTC в секундах и имя зоныinfo, например "Европа/Вена" , и возвращает смещение в секунд от локального времени и UTC для этого момента времени.

В C это будет:

/* ... code to to set local time to the time zone I want to compare against,
   not shown here. Then call function below to get difference vs localtime.
   Hardly an ideal solution,
   but just to demonstrate what I want in a "lingua franca" (C): */


int get_diff_vs_localtime(const time_t original_utc_time)
{
    struct tm* ts;

    ts = localtime(&original_utc_time);

    return mktime(ts) - original_utc_time;
}

Я думаю, мой вопрос действительно сводится к: "учитывая часовой пояс Olson (пример" Европа/Стокгольм") и время UTC, что является местным временем?

Ответ 1

Предполагая "время UTC в секундах" означает временную метку POSIX. Чтобы преобразовать его в Стокгольмское время:

from datetime import datetime
import pytz

tz = pytz.timezone('Europe/Stockholm')

utc_dt = datetime.utcfromtimestamp(posix_timestamp).replace(tzinfo=pytz.utc)
dt = tz.normalize(utc_dt.astimezone(tz))
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))

tz.normalize() не требуется, если исходный часовой пояс UTC (как в этом случае).

Более простой альтернативой является использование параметра fromtimestamp() tz для преобразования "секунд с эпохи" в локальное время:

from datetime import datetime
import pytz

tz = pytz.timezone('Europe/Stockholm')

dt = datetime.fromtimestamp(posix_timestamp, tz)
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))

Оба примера дают одинаковый результат.

Если локальная машина использует "правильные" часовые пояса, то для преобразования временной метки POSIX, полученной от внешнего источника в UTC, можно использовать явную формулу:

from datetime import datetime, timedelta
import pytz

utc_dt = datetime(1970, 1, 1, tzinfo=pytz.utc) + timedelta(seconds=posix_timestamp)

Последняя формула может также поддерживать более широкий диапазон дат (менее вероятные проблемы с датами до 1970 года, после 2038 или 3000 лет).

Если временная метка исходит от локального "правильного" источника, тогда вместо этого следует использовать первые два примера (они называются "right" time.gmtime()).

Ответ 2

Вы можете использовать pytz и datetime сделать что-то таким образом:

from datetime import datetime
from pytz import timezone

def get_diff(now, tzname):
    tz = timezone(tzname)
    utc = timezone('UTC')
    utc.localize(datetime.now())
    delta =  utc.localize(now) - tz.localize(now)
    return delta

Что для следующего примера...

now = datetime.utcnow()
print(now)
tzname = 'Europe/Stockholm'
delta = get_diff(now, tzname)
print(delta)
now_in_stockholm = now + delta
print(now_in_stockholm)

... выходы:

2012-10-02 14:38:56.547475
2:00:00
2012-10-02 16:38:56.547475

Ответ 3

Я думаю, мой вопрос действительно сводится к: "учитывая часовой пояс Олсона (пример" Европа/Стокгольм") и время UTC, каково местное время?

Если я правильно понимаю вашу проблему:

from pytz import timezone
import datetime, time

tz = timezone('Asia/Kuwait')
utc_dt = datetime.datetime.utcfromtimestamp(time.time())
utc_dt + tz.utcoffset(utc_dt)

>>> tz.utcoffset(utc_dt).seconds
10800
>>> tz
<DstTzInfo 'Asia/Kuwait' LMT+3:12:00 STD>
>>> utc_dt + tz.utcoffset(utc_dt)
datetime.datetime(2012, 10, 2, 17, 13, 53, 504322)
>>> utc_dt
datetime.datetime(2012, 10, 2, 14, 13, 53, 504322)

Ответ 4

Это довольно старый, но я не мог найти отличный ответ, поэтому вот что я придумал:

from datetime import datetime
local = datetime.now()
utc = datetime.utcnow()
int((local - utc).days * 86400 + round((local - utc).seconds, -1))

Возвращает:

-21600

потому что я (сейчас) 21600 секунд (6 часов) позади UTC.

Примечание: вторая дата, рассчитанная (в этом случае UTC), должна быть округлена, так как при каждом расчете есть очень маленькая разница во времени.