我现在有服务器本地时间和一个小时转移到UTC(说+5,-8等),我怎么能恢复到UTC?
请注意,由于夏令时的原因,它并不像直观的那样。目前我在EDT,应该是UTC+5,但事实上,在夏天,我们只有+4。不幸的是,我不(想)知道服务器的时区,所以我不确定是否有可能计算给定信息的UTC。
我的目标语言是python,但如果存在解决方案,语言本身应该不是一个大问题。
为什么我有这样的限制,就是因为这个。它只是没有返回一个好的文本时区描述,而是返回一个数字。
下面是我的服务器在实践中的一个真实元素:
<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。
如果你不(想)知道实际的时区,那么不,通常是不可能的,因为有些时区现在可能有相同的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偏移量。
您可以使用一些附加信息(例如,国家)来消除歧义。