2013-04-22 6 views
7

In un ambiente Windows pitone posso ottenere il fuso orario locale come questo, ma non è utilizzabile con pytz:Come posso convertire i fusi orari delle finestre in fusi orari compresi in pytz?

>>> import win32timezone 
>>> win32timezone.TimeZoneInfo.local() 
TimeZoneInfo(u'US Mountain Standard Time', True) 
>>> win32timezone.TimeZoneInfo.local().timeZoneName 
u'US Mountain Standard Time' 
>>> tz = pytz.timezone(win32timezone.TimeZoneInfo.local().timeZoneName) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "C:\Python27\lib\site-packages\pytz\__init__.py", line 185, in timezone 
    raise UnknownTimeZoneError(zone) 
pytz.exceptions.UnknownTimeZoneError: 'US Mountain Standard Time' 

Che cosa è un buon modo per convertire l'output a un nome di fuso orario pytz.timezone() capirà?


Ecco la risposta utilizzando tzlocal (grazie a Matt):

>>> from tzlocal.win32 import get_localzone_name 
>>> get_localzone_name() 
'America/Phoenix' 
>>> tz = pytz.timezone(get_localzone_name()) 
>>> tz 
<DstTzInfo 'America/Phoenix' MST-1 day, 17:00:00 STD> 

risposta

9

Non fare alcuna ipotesi su cosa sia un ID del fuso orario di Windows in base al suo nome. Ad esempio, US Mountain Standard Time è in realtà il fuso orario di Windows per la maggior parte dell'Arizona, che è permanentemente in MST perché non implementa l'ora legale. Ma l'ID di Windows per il resto del fuso orario di montagna è Mountain Standard Time - che fa segue l'ora legale durante l'ora legale di montagna, tuttavia l'ID del fuso orario non cambia! L'unica differenza tra gli ID di queste due zone è il prefisso "US". Nel database IANA/Olson, queste sono due zone molto distinte: America/Phoenix e America/Denver.

Sono necessari i mapping da Windows a ID del fuso orario di Olson forniti dal progetto CLDR Unicode. Leggi lo TimeZone tag wiki per informazioni e collegamenti. Sono incerto se esiste già una libreria che implementa questo in Python - potrebbe essere necessario fare qualche ricerca, o implementarla da soli dai dati grezzi.

UPDATE

Un po 'di ricerca, e ho trovato una libreria Python chiamato tzlocal che ha le mappature CLDR. È anche abbastanza gentile includere uno script che andrà a recuperare i mapping correnti dal sito Web CLDR e aggiornarsi. Non l'ho provato da solo, ma sembra avere l'approccio corretto. Si concentra principalmente sulla restituzione del fuso orario attuale del sistema, in un id IANA/Olson adatto per l'uso con pytz. Here is the author's blog post describing its usage.

+0

Matt, grazie per averlo indicato. Questo sembra un problema più complicato di quanto pensassi all'inizio. È strano che non ci sia una libreria Python di Windows che tenga conto di tutto ciò ... –

+0

Il database Olson è superiore in ogni modo, ed è questo che implementa pytz. C'è un motivo per cui devi lavorare con i fusi orari di Windows? –

+0

Forse non l'ho visto, ma c'è un modo per usare pytz per ottenere il nome Olsen del fuso orario attuale della macchina? –

4

Anurag Uniyal has posted un modo alternativo per scoprire i nomi di fuso orario che siano coerenti con la tzname e utcoffset riportato dal computer.


Facendo seguito alla soluzione di Matt Johnson, ecco come si può caricare il Unicode Common Locale Data Repository (CLDR) mapping da ID di fuso orario di Windows per i nomi di fuso orario Olson:

import lxml.etree as ET 
import collections 
import pprint 
result = {} 
doc = ET.parse('http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml') 
for zone in doc.xpath('//mapZone'): 
    attrib = zone.attrib 
    if attrib['territory'] == '001': 
     result[attrib['other']] = attrib['type'] 
pprint.pprint(dict(result)) 

rendimenti

{'AUS Central Standard Time': 'Australia/Darwin', 
'AUS Eastern Standard Time': 'Australia/Sydney', 
'Afghanistan Standard Time': 'Asia/Kabul', 
'Alaskan Standard Time': 'America/Anchorage', 
'Arab Standard Time': 'Asia/Riyadh', 
'Arabian Standard Time': 'Asia/Dubai', 
'Arabic Standard Time': 'Asia/Baghdad', 
'Argentina Standard Time': 'America/Buenos_Aires', 
'Atlantic Standard Time': 'America/Halifax', 
'Azerbaijan Standard Time': 'Asia/Baku', 
'Azores Standard Time': 'Atlantic/Azores', 
'Bahia Standard Time': 'America/Bahia', 
'Bangladesh Standard Time': 'Asia/Dhaka', 
'Canada Central Standard Time': 'America/Regina', 
'Cape Verde Standard Time': 'Atlantic/Cape_Verde', 
'Caucasus Standard Time': 'Asia/Yerevan', 
'Cen. Australia Standard Time': 'Australia/Adelaide', 
'Central America Standard Time': 'America/Guatemala', 
'Central Asia Standard Time': 'Asia/Almaty', 
'Central Brazilian Standard Time': 'America/Cuiaba', 
'Central Europe Standard Time': 'Europe/Budapest', 
'Central European Standard Time': 'Europe/Warsaw', 
'Central Pacific Standard Time': 'Pacific/Guadalcanal', 
'Central Standard Time': 'America/Chicago', 
'Central Standard Time (Mexico)': 'America/Mexico_City', 
'China Standard Time': 'Asia/Shanghai', 
'Dateline Standard Time': 'Etc/GMT+12', 
'E. Africa Standard Time': 'Africa/Nairobi', 
'E. Australia Standard Time': 'Australia/Brisbane', 
'E. Europe Standard Time': 'Asia/Nicosia', 
'E. South America Standard Time': 'America/Sao_Paulo', 
'Eastern Standard Time': 'America/New_York', 
'Egypt Standard Time': 'Africa/Cairo', 
'Ekaterinburg Standard Time': 'Asia/Yekaterinburg', 
'FLE Standard Time': 'Europe/Kiev', 
'Fiji Standard Time': 'Pacific/Fiji', 
'GMT Standard Time': 'Europe/London', 
'GTB Standard Time': 'Europe/Bucharest', 
'Georgian Standard Time': 'Asia/Tbilisi', 
'Greenland Standard Time': 'America/Godthab', 
'Greenwich Standard Time': 'Atlantic/Reykjavik', 
'Hawaiian Standard Time': 'Pacific/Honolulu', 
'India Standard Time': 'Asia/Calcutta', 
'Iran Standard Time': 'Asia/Tehran', 
'Israel Standard Time': 'Asia/Jerusalem', 
'Jordan Standard Time': 'Asia/Amman', 
'Kaliningrad Standard Time': 'Europe/Kaliningrad', 
'Korea Standard Time': 'Asia/Seoul', 
'Magadan Standard Time': 'Asia/Magadan', 
'Mauritius Standard Time': 'Indian/Mauritius', 
'Middle East Standard Time': 'Asia/Beirut', 
'Montevideo Standard Time': 'America/Montevideo', 
'Morocco Standard Time': 'Africa/Casablanca', 
'Mountain Standard Time': 'America/Denver', 
'Mountain Standard Time (Mexico)': 'America/Chihuahua', 
'Myanmar Standard Time': 'Asia/Rangoon', 
'N. Central Asia Standard Time': 'Asia/Novosibirsk', 
'Namibia Standard Time': 'Africa/Windhoek', 
'Nepal Standard Time': 'Asia/Katmandu', 
'New Zealand Standard Time': 'Pacific/Auckland', 
'Newfoundland Standard Time': 'America/St_Johns', 
'North Asia East Standard Time': 'Asia/Irkutsk', 
'North Asia Standard Time': 'Asia/Krasnoyarsk', 
'Pacific SA Standard Time': 'America/Santiago', 
'Pacific Standard Time': 'America/Los_Angeles', 
'Pacific Standard Time (Mexico)': 'America/Santa_Isabel', 
'Pakistan Standard Time': 'Asia/Karachi', 
'Paraguay Standard Time': 'America/Asuncion', 
'Romance Standard Time': 'Europe/Paris', 
'Russian Standard Time': 'Europe/Moscow', 
'SA Eastern Standard Time': 'America/Cayenne', 
'SA Pacific Standard Time': 'America/Bogota', 
'SA Western Standard Time': 'America/La_Paz', 
'SE Asia Standard Time': 'Asia/Bangkok', 
'Samoa Standard Time': 'Pacific/Apia', 
'Singapore Standard Time': 'Asia/Singapore', 
'South Africa Standard Time': 'Africa/Johannesburg', 
'Sri Lanka Standard Time': 'Asia/Colombo', 
'Syria Standard Time': 'Asia/Damascus', 
'Taipei Standard Time': 'Asia/Taipei', 
'Tasmania Standard Time': 'Australia/Hobart', 
'Tokyo Standard Time': 'Asia/Tokyo', 
'Tonga Standard Time': 'Pacific/Tongatapu', 
'Turkey Standard Time': 'Europe/Istanbul', 
'US Eastern Standard Time': 'America/Indianapolis', 
'US Mountain Standard Time': 'America/Phoenix', 
'UTC': 'Etc/GMT', 
'UTC+12': 'Etc/GMT-12', 
'UTC-02': 'Etc/GMT+2', 
'UTC-11': 'Etc/GMT+11', 
'Ulaanbaatar Standard Time': 'Asia/Ulaanbaatar', 
'Venezuela Standard Time': 'America/Caracas', 
'Vladivostok Standard Time': 'Asia/Vladivostok', 
'W. Australia Standard Time': 'Australia/Perth', 
'W. Central Africa Standard Time': 'Africa/Lagos', 
'W. Europe Standard Time': 'Europe/Berlin', 
'West Asia Standard Time': 'Asia/Tashkent', 
'West Pacific Standard Time': 'Pacific/Port_Moresby', 
'Yakutsk Standard Time': 'Asia/Yakutsk'} 

Se non lo fai desideri che il tuo programma dipenda da lxml o da una connessione di rete, potresti inserire questo dict in un modulo e usarlo da lì.

+0

tecnica interessante ... lo eseguirò attraverso alcuni dei miei fusi orari comuni domani e ti faccio sapere come funziona! –

+0

Le corrispondenze ravvicinate non sono una buona idea quando si parla di ID di qualcosa. Se fossero solo nomi, allora certo. Ma gli ID specifici di ogni zona hanno significati molto particolari. Vedi la mia risposta per maggiori dettagli. –

+0

Link interessante nel tuo aggiornamento. Sono curioso però - come questo aiuta con le zone di Windows? Inoltre, non capisco quali dati sorgente stanno guardando in quel post, affermano che stanno ottenendo il valore dalla variabile 'TZ' di linux, ma per quanto posso dire, questo è già un identificativo Olson, no? –