在给定本地时间和几何时间偏移的情况下,是否可以“恢复”UTC时间?

2024-06-16 13:56:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我现在有服务器本地时间和一个小时到UTC的班次(比如+5、-8等),如何将其恢复到UTC?你知道吗

请注意,由于夏季的原因,这并不像它那样直观。目前我在美国东部时间,这应该是UTC+5,但事实上,在夏天,我们只有+4。不幸的是,我不想知道服务器的时区,所以我不确定是否可以用给定的信息计算UTC。你知道吗

我的目标语言是python,但是如果有解决方案的话,语言本身应该不是什么大问题。你知道吗

我为什么有这样的限制,是因为this。它只是不返回一个好的文本时区描述,而不是一个数字。你知道吗

以下是我的服务器中的一个实际元素:

<RegionalSettings>
  <Language>1033</Language>
  <Locale>1033</Locale>
  <AdvanceHijri>0</AdvanceHijri>
  <CalendarType>1</CalendarType>
  <Time24>False</Time24>
  <TimeZone>300</TimeZone>
  <SortOrder>2070</SortOrder>
  <Presence>True</Presence>
</RegionalSettings>

注意这里的时区字段

<TimeZone>300</TimeZone>

它以分钟为单位,所以它告诉我我在UTC+5的某个地方,但不是一个诚实的时间转换到UTC。你知道吗


Tags: 服务器时间原因languagelocaleutctimezone小时
1条回答
网友
1楼 · 发布于 2024-06-16 13:56:01

如果您不(想)知道实际时区,那么不,这通常是不可能的,因为某些时区现在可能有相同的utc偏移量,而使用不同的DST规则。你知道吗

可以根据本地时间和“标准”utc偏移量生成候选时区和utc时间的列表:

#!/usr/bin/env python
from collections import defaultdict
from datetime import datetime, timedelta
from pprint import pprint
import pytz # $ pip install pytz

local_time = datetime(2015, 8, 13, 16, 15)
# standard offset (the current offset may be different)
#NOTE: opposite sign!   it is not POSIX-style offset
standard_utc_offset_hours = timedelta(hours=-5)

# find all timezones with the same utc offset (in the recent time ~2y)
now = datetime.utcnow()
recent = now.replace(year=now.year - 2)
timezones = defaultdict(set) # recent utc offsets -> timezones
times = set()
for tz in map(pytz.timezone, pytz.all_timezones_set):
    # bisect(_utc_transition_times, input_utc_time) -> index
    # _transition_info[index] -> (offset, dst, tzname)
    # _tzinfos[offset, dst, tzname] -> timezone as pytz tzinfo object
    d = tz.fromutc(now)
    info = d.utcoffset(), d.dst(), d.tzname()
    for i, (offset, dst, tzname) in enumerate(getattr(tz, '_transition_info', [info])):
        if offset == standard_utc_offset_hours:  # same "standard" offset
            times.add(str(tz.localize(local_time, is_dst=None)))
            # group by recent utc offsets
            if not hasattr(tz, '_utc_transition_times'):
                timezones[d.strftime("%z"),].add(tz.zone)
                break
            elif tz._utc_transition_times[i] > recent: # recent rules
                it = (tz.fromutc(t).strftime("%z") for t in tz._utc_transition_times[i:])
                timezones[tuple(set(it))].add(tz.zone)
                break
pprint(times)
pprint(timezones)

输出

{'2015-08-13 16:15:00-03:00',
 '2015-08-13 16:15:00-04:00',
 '2015-08-13 16:15:00-05:00',
 '2015-08-13 16:15:00-06:00'}
{('-0500',): {'America/Eirunepe',
              'America/Porto_Acre',
              'America/Rio_Branco',
              'Brazil/Acre',
              'EST',
              'Etc/GMT+5'},
 ('-0500', '-0400'): {'America/Cayman',
                      'America/Detroit',
                      'America/Fort_Wayne',
                      'America/Grand_Turk',
                      'America/Havana',
                      'America/Indiana/Indianapolis',
                      'America/Indiana/Marengo',
                      'America/Indiana/Petersburg',
                      'America/Indiana/Vevay',
                      'America/Indiana/Vincennes',
                      'America/Indiana/Winamac',
                      'America/Indianapolis',
                      'America/Iqaluit',
                      'America/Kentucky/Louisville',
                      'America/Kentucky/Monticello',
                      'America/Louisville',
                      'America/Montreal',
                      'America/Nassau',
                      'America/New_York',
                      'America/Nipigon',
                      'America/Pangnirtung',
                      'America/Port-au-Prince',
                      'America/Thunder_Bay',
                      'America/Toronto',
                      'Canada/Eastern',
                      'Cuba',
                      'EST5EDT',
                      'US/East-Indiana',
                      'US/Eastern',
                      'US/Michigan'},
 ('-0500', '-0600'): {'America/Bahia_Banderas',
                      'America/Cancun',
                      'America/Chicago',
                      'America/Indiana/Knox',
                      'America/Indiana/Tell_City',
                      'America/Knox_IN',
                      'America/Matamoros',
                      'America/Menominee',
                      'America/Merida',
                      'America/Mexico_City',
                      'America/Monterrey',
                      'America/North_Dakota/Beulah',
                      'America/North_Dakota/Center',
                      'America/North_Dakota/New_Salem',
                      'America/Rainy_River',
                      'America/Rankin_Inlet',
                      'America/Resolute',
                      'America/Winnipeg',
                      'CST6CDT',
                      'Canada/Central',
                      'Chile/EasterIsland',
                      'Mexico/General',
                      'Pacific/Easter',
                      'US/Central',
                      'US/Indiana-Starke'}}

根据您选择的时区,对于相同的本地时间和“标准”utc偏移量,可能有四个不同的utc时间。你知道吗


可以根据本地时间和相应的utc偏移量(相同的utc时间)生成候选时区列表:

#!/usr/bin/env python
from collections import defaultdict
from datetime import datetime, timedelta
from pprint import pprint
import pytz # $ pip install pytz

local_time = datetime(2015, 8, 13, 16, 15)
utc_offset_hours = -4 #NOTE: opposite sign!   it is not POSIX-style offset

# <local time> = <utc time> + <utc offset>
utc_time = local_time - timedelta(hours=utc_offset_hours)
winter_time = datetime(2015, 1, 1) # northern hemisphere
timezones = defaultdict(list) # winter utc offset -> zones
for tz in map(pytz.timezone, pytz.all_timezones_set):
    tz_time = tz.fromutc(utc_time)
    if tz_time.replace(tzinfo=None) == local_time: # same utc offset now
        # group by winter utc offset
        timezones[tz.fromutc(winter_time).strftime("%Z%z")].append(tz.zone)
pprint(timezones)

输出

{'AMST-0300': ['America/Cuiaba', 'America/Campo_Grande'],
 'AMT-0400': ['Brazil/West',
              'America/Porto_Velho',
              'America/Boa_Vista',
              'America/Manaus'],
 'AST-0400': ['America/Anguilla',
              'America/Antigua',
              'America/Santo_Domingo',
              'America/St_Barthelemy',
              'America/St_Lucia',
              'America/Lower_Princes',
              'America/Blanc-Sablon',
              'America/Martinique',
              'America/Montserrat',
              'America/Grenada',
              'America/Curacao',
              'America/Virgin',
              'America/Kralendijk',
              'America/Puerto_Rico',
              'America/Guadeloupe',
              'America/Dominica',
              'America/Port_of_Spain',
              'America/Aruba',
              'America/Barbados',
              'America/St_Vincent',
              'America/St_Kitts',
              'America/Tortola',
              'America/Marigot',
              'America/St_Thomas'],
 'BOT-0400': ['America/La_Paz'],
 'CST-0500': ['America/Havana', 'Cuba'],
 'EST-0500': ['EST5EDT',
              'America/Fort_Wayne',
              'America/Toronto',
              'America/Kentucky/Monticello',
              'America/Indiana/Vevay',
              'America/Iqaluit',
              'US/East-Indiana',
              'America/Indiana/Vincennes',
              'America/Indiana/Petersburg',
              'US/Eastern',
              'America/Louisville',
              'America/Nassau',
              'America/Indiana/Winamac',
              'Canada/Eastern',
              'America/Nipigon',
              'America/Grand_Turk',
              'America/Port-au-Prince',
              'America/Montreal',
              'America/Thunder_Bay',
              'America/Kentucky/Louisville',
              'America/Detroit',
              'America/New_York',
              'America/Indiana/Indianapolis',
              'America/Pangnirtung',
              'America/Indiana/Marengo',
              'US/Michigan',
              'America/Indianapolis'],
 'GMT+4-0400': ['Etc/GMT+4'],
 'GYT-0400': ['America/Guyana'],
 'PYST-0300': ['America/Asuncion']}

如您所见,即使某些时区今天使用相同的utc偏移量,它们也可能在不同的日期使用不同的utc偏移量。你知道吗

你可以使用一些额外的信息(例如,国家)来消除歧义。你知道吗

相关问题 更多 >