簡體   English   中英

如何計算python中兩個時區之間的時差?

[英]How to compute the time difference between two time zones in python?

如何計算 Python 中兩個時區之間的時差? 也就是說,我不想比較 TZ-aware datetime對象並獲得timedelta 我想比較兩個TimeZone對象並獲得一個offset_hours datetime庫中沒有任何內容可以處理此問題, pytz也沒有。

您必須知道的第一件事是,兩個時區之間的偏移量不僅取決於相關時區,還取決於您詢問的日期。 例如,夏令時開始和結束的日期在 2007 年在美國發生了變化。雖然基本的時區物流在任何一個地方都很少發生變化,但全球的變化率卻不容忽視。 因此,您必須將相關日期合並到您的函數中。

完成必要的前言后,如果您利用鍾擺庫,實際功能並不太難編寫。 它應該是這樣的:

import pendulum

def tz_diff(home, away, on=None):
    """
    Return the difference in hours between the away time zone and home.

    `home` and `away` may be any values which pendulum parses as timezones.
    However, recommended use is to specify the full formal name.
    See https://gist.github.com/pamelafox/986163

    As not all time zones are separated by an integer number of hours, this
    function returns a float.

    As time zones are political entities, their definitions can change over time.
    This is complicated by the fact that daylight savings time does not start
    and end on the same days uniformly across the globe. This means that there are
    certain days of the year when the returned value between `Europe/Berlin` and
    `America/New_York` is _not_ `6.0`.

    By default, this function always assumes that you want the current
    definition. If you prefer to specify, set `on` to the date of your choice.
    It should be a `Pendulum` object.

    This function returns the number of hours which must be added to the home time
    in order to get the away time. For example,
    ```python
    >>> tz_diff('Europe/Berlin', 'America/New_York')
    -6.0
    >>> tz_diff('Europe/Berlin', 'Asia/Kabul')
    2.5
    ```
    """
    if on is None:
        on = pendulum.today()
    diff = (on.timezone_(home) - on.timezone_(away)).total_hours()

    # what about the diff from Tokyo to Honolulu? Right now the result is -19.0
    # it should be 5.0; Honolulu is naturally east of Tokyo, just not so around
    # the date line
    if abs(diff) > 12.0:
        if diff < 0.0:
            diff += 24.0
        else:
            diff -= 24.0

    return diff

正如文檔中所述,當您掃過一年中的幾天時,您可能無法在任何兩個給定位置之間獲得穩定的結果。 但是,實現一個選擇當前年份天數的中值結果的變體是留給讀者的練習。

這是一個使用 Python 庫 Pytz 的解決方案,它解決了夏令時結束時時間不明確的問題。


from pytz import timezone
import pandas as pd

def tz_diff(date, tz1, tz2):
    '''
    Returns the difference in hours between timezone1 and timezone2
    for a given date.
    '''
    date = pd.to_datetime(date)
    return (tz1.localize(date) - 
            tz2.localize(date).astimezone(tz1))\
            .seconds/3600

下面的示例分別計算 UTC 和澳大利亞時間在 1 月 1 日和 6 月 1 日之間的時差。 請注意如何考慮夏令時。

utc = timezone('UTC')
aus = timezone('Australia/Sydney')

tz_diff('2017-01-01', utc, aus)

# 11.0

tz_diff('2017-06-01', utc, aus)

# 10.0

謝謝

這是另一個解決方案:

from datetime import datetime
from pytz import timezone
from dateutil.relativedelta import relativedelta

utcnow = timezone('utc').localize(datetime.utcnow()) # generic time
here = utcnow.astimezone(timezone('US/Eastern')).replace(tzinfo=None)
there = utcnow.astimezone(timezone('Asia/Ho_Chi_Minh')).replace(tzinfo=None)

offset = relativedelta(here, there) 
offset.hours

這里我們要做的是將時間轉換為兩個不同的時區。 然后,我們刪除了時區信息,這樣當您使用relativedelta 計算兩者之間的差異時,我們會欺騙它認為這是兩個不同的時刻,而不是不同時區的同一時刻。

上述結果將返回 -11,但由於美國/東部遵守夏令時而亞洲/Ho_Chi_Minh 不遵守,因此該金額全年可能會發生變化。

這是一個代碼片段,用於獲取 UTC 和美國/東部之間的差異,但它應該適用於任何兩個時區。

# The following algorithm will work no matter what is the local timezone of the server,
# but for the purposes of this discussion, let's assume that the local timezone is UTC.
local_timestamp = datetime.now()
# Assume that utc_timestamp == 2019-01-01 12:00.
utc_timestamp = pytz.utc.localize(local_timestamp)
# If it was 12:00 in New York, it would be 20:00 in UTC. So us_eastern_timestamp is a UTC
# timestamp with the value of 2019-01-01 20:00.
us_eastern_timestamp = timezone("US/Eastern").localize(local_timestamp).astimezone(pytz.utc)
# delta is a Python timedelta object representing the interval between the two timestamps,
# which, in our example, is -8 hours.
delta = utc_timestamp - us_eastern_timestamp
# In the last line, we convert the timedelta into an integer representing the number of
# hours.
print round(delta.total_seconds() / 60.0 / 60.0)

(tz_from.localize(date) - tz_to.localize(date)).seconds/3600.0

其中 tz_from 和 tz_to 是開始和結束時區。 您必須指定特定日期。

我創建了兩個函數來處理時區。

import datetime

import pytz

def diff_hours_tz(from_tz_name, to_tz_name, negative=False):
    """
    Returns difference hours  between timezones
    res = diff_hours_tz("UTC", "Europe/Paris") : 2
    """
    from_tz = pytz.timezone(from_tz_name)
    to_tz = pytz.timezone(to_tz_name)

    utc_dt = datetime.datetime.now(datetime.timezone.utc)
    dt_from = dt_to = datetime.datetime.utcnow()

    dt_from = from_tz.localize(dt_from)
    dt_to = to_tz.localize(dt_to)

    from_d = dt_from - utc_dt
    if from_d.days < 0:
        return diff_hours_tz(to_tz_name, from_tz_name, True)

    dt_delta = dt_from - dt_to

    negative_int = -1 if negative else 1

    return int(dt_delta.seconds/3600)*negative_int

def dt_tz_to_tz(dt, from_tz_name, to_tz_name):
    """
    Apply difference hours between timezones to a datetime object
    dt_new = dt_tz_to_tz(datetime.datetime.now(), "UTC", "Europe/Paris")
    """
    hours = diff_hours_tz(from_tz_name, to_tz_name)
    return dt+datetime.timedelta(hours=hours)

# Usage example

res = diff_hours_tz("Europe/Paris", "America/New_York")
# Result : -6
res = diff_hours_tz("UTC", "Europe/Paris")
# Result : 2

now = datetime.datetime.now()
# Result : 2019-06-18 15:10:31.720105
dt_new = dt_tz_to_tz(now, "UTC", "Europe/Paris")
# Result : 2019-06-18 17:10:31.720105
dt_new = dt_tz_to_tz(now, "Europe/Paris", "America/New_York")
# Result : 2019-06-18 09:10:31.720105
dt_new = dt_tz_to_tz(now, "America/New_York", "Europe/Paris")
# Result : 2019-06-18 21:10:31.720105

我希望它會有所幫助!

from datetime import datetime
from zoneinfo import ZoneInfo

dt = datetime.now() # 2020-09-13
tz0, tz1 = "Europe/Berlin", "US/Eastern" # +2 vs. -4 hours rel. to UTC

utcoff0, utcoff1 = dt.astimezone(ZoneInfo(tz0)).utcoffset(), dt.astimezone(ZoneInfo(tz1)).utcoffset()

print(f"hours offset between {tz0} -> {tz1} timezones: {(utcoff1-utcoff0).total_seconds()/3600}")
>>> hours offset between Europe/Berlin -> US/Eastern timezones: -6.0
  • 一種使用Python 3.9的標准庫來做到這一點的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM