используя pytz, чтобы получить местное название часового пояса [дубликат]

Используя ваш пример dataframe, мы могли бы:

xtabs(value ~ name + numbers, data = dat1)
46
задан Matt Joiner 19 October 2011 в 02:09
поделиться

11 ответов

Я думаю, что лучше всего пройти через все временные точки pytz и проверить, какой из них соответствует местному часовому поясу, каждый объект часового пояса pytz содержит информацию об utcoffset и tzname, таких как CDT, EST, о той же информации о локальном времени можно получить из time.timezone/altzone и time.tzname, и я думаю, что этого достаточно, чтобы правильно совместить локальный часовой пояс в базе данных pytz, например

import time
import pytz
import datetime

local_names = []
if time.daylight:
    local_offset = time.altzone
    localtz = time.tzname[1]
else:
    local_offset = time.timezone
    localtz = time.tzname[0]

local_offset = datetime.timedelta(seconds=-local_offset)

for name in pytz.all_timezones:
    timezone = pytz.timezone(name)
    if not hasattr(timezone, '_tzinfos'):
        continue#skip, if some timezone doesn't have info
    # go thru tzinfo and see if short name like EDT and offset matches
    for (utcoffset, daylight, tzname), _ in timezone._tzinfos.iteritems():
        if utcoffset == local_offset and tzname == localtz:
            local_names.append(name)

print local_names

вывод:

['America / Atikokan', 'America «Америка / Чикаго», «Америка / Чихуахуа», «Америка / Корал-Харбор», «Америка / «Америка / Индиана», «Америка / Индиана / Маренго», «Америка / Индиана / Индиана», «Америка / Индиана / Индиана», «Америка / Индиана / «Америка / Индиана / Петербург», «Америка / Индиана / Телль_Чита», «Америка / Индиана / Вевай», «Америка / Индиана / Венсенн», «Америка / Индиана / Винамак», «Америка / Индианаполис», «Америка / Икалуит ',' Америка / Кентукки / Луисвилл ',' Америка / Кентукки / L «Америка / Кентукки», «Америка / Нокс_Ин», «Америка / Луисвилл», «Америка / Луисвилл», «Америка / Манагуа», «Америка / Матаморос», «Америка / Меномине», «Америка / «Америка / Мексика», «Америка / Монтеррей», «Америка / Северная_Дакота / Беулах», «Америка / Северная_Дакота / Центр», «Америка / Северная_Дакота / Нью-Салем», «Америка / Ожинага», «Америка / Пангнирунг», «Америка / Режиссер», «Америка / Резолюция», «Америка / Резолюция», «Америка / Тегусигальпа», «Америка / Виннипег», «CST6CDT», «Канада / Центральная», «Мексика /

В процессе производства вы можете создать такое сопоставление заранее и сохранить его вместо

Тестирование скрипта после изменения часового пояса:

$ export TZ = 'Австралия / Сидней' $ python get_tz_names.py ['Антарктика / Macquarie', 'Австралия / ACT ',' Австралия / Брисбен ',' Австралия / Канберра ',' Австралия / Керри ',' Австралия / Хобарт ',' Австралия / Линдеман ',' Австралия ia / Melbourne ',' Австралия / NSW ',' Австралия / Квинсленд ',' Австралия / Сидней ',' Австралия / Тасмания ',' Австралия / Виктория ']

17
ответ дан user7116 20 August 2018 в 15:51
поделиться
  • 1
    Этот алгоритм дает наилучшие результаты до сих пор, но он не кажется таким же чистым, как ответ @ pcperini. – Matt Joiner 2 December 2011 в 04:41
  • 2
    @Matt Joiner, я думаю, что это чистый код и более точный, поскольку вместо названия страны он сравнивает смещения – Anurag Uniyal 2 December 2011 в 05:52
  • 3
    @MattJoiner, также я не думаю, что код страны, полученный из URL-адреса, изменится, изменится ли настройка TZ системы? – Anurag Uniyal 2 December 2011 в 05:54
  • 4
    Чтобы узнать, действует ли DST: if time.daylight and time.localtime().tm_isdst > 0. Примечание: time.daylight только указывает, имеет ли локальный часовой пояс DST вообще, он ничего не говорит о текущем состоянии. – jfs 2 August 2013 в 12:36

Если оценка /etc/localtime подходит для вас, может получиться следующий трюк: после перевода на python:

> md5sum /etc/localtime
abcdefabcdefabcdefabcdefabcdefab /etc/localtime
> find /usr/share/zoneinfo -type f |xargs md5sum | grep abcdefabcdefabcdefabcdefabcdefab
abcdefabcdefabcdefabcdefabcdefab /usr/share/zoneinfo/Europe/London
abcdefabcdefabcdefabcdefabcdefab /usr/share/zoneinfo/posix/Europe/London
...

Дубликаты могут быть отфильтрованы с использованием только официальных названий регионов «Европа», «Америка» ... Если есть еще дубликаты, вы можете взять кратчайшее имя: -)

8
ответ дан A.H. 20 August 2018 в 15:51
поделиться

Это даст вам имя часового пояса, в зависимости от того, что находится в переменной TZ, или файл локального времени, если он не установлен:

#! /usr/bin/env python

import time

time.tzset
print time.tzname
2
ответ дан Diego Torres Milano 20 August 2018 в 15:51
поделиться
  • 1
    К сожалению, он возвращает кортеж из трех буквенных кодов часового пояса, а не полного имени часового пояса. – Matt Joiner 6 October 2011 в 05:25
  • 2
    Даже если вы построите таблицу поиска для этого, это будет неоднозначно. & Quot; EST & Quot; может быть America/New_York или Australia/Sydney. & Quot; БСТ & Quot; может быть Europe/London или Asia/Dhaka. – wberry 10 October 2011 в 20:37
  • 3
    Он прав. Единственное, что система знает о своем часовом поясе - это настройки GMT offset и DST. В linux они задаются либо переменной окружения TZ (обычно не заданной), либо файлом / etc / localtime, который может быть либо ссылкой на одно из определений часового пояса, найденное в / usr / share / zoneinfo, либо копию один из них. Просто невозможно получить это значение в общем случае, если вы точно не знаете, что система, в которой выполняется ваш скрипт, настраивается с использованием символической ссылки или переменной окружения. Тогда вы, вероятно, могли бы запустить системные команды из python, чтобы получить его. – Yanick Girouard 19 October 2011 в 17:55
  • 4
    @YanickGirouard: Какие системные команды? – Matt Joiner 2 December 2011 в 04:36
  • 5
    All all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all All all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all all – Yanick Girouard 3 December 2011 в 07:43

Я предпочитаю следовать немного лучше, чем ковырять значения _xxx

import time, pytz, os

cur_name=time.tzname
cur_TZ=os.environ.get("TZ")

def is_current(name):
   os.environ["TZ"]=name
   time.tzset()
   return time.tzname==cur_name

print "Possible choices:", filter(is_current, pytz.all_timezones)

# optional tz restore
if cur_TZ is None: del os.environ["TZ"]
else: os.environ["TZ"]=cur_TZ
time.tzset()
0
ответ дан korc 20 August 2018 в 15:51
поделиться
  • 1
    Использование переменной окружения TZ работает только для Linux (или Unix), а не для Windows. – saeedgnu 30 July 2013 в 01:35
  • 2
    Другое дело, что он не работает вообще на моей текущей Fedora (F20), такой переменной TZ нет. – Vinzenz 22 May 2014 в 13:09

Модуль tzlocal для Python направлен именно на эту проблему. Он дает согласованные результаты как в Linux, так и в Windows, правильно преобразовывая идентификаторы временного пояса Windows в Olson с использованием сопоставлений CLDR.

4
ответ дан Matt Johnson 20 August 2018 в 15:51
поделиться

Это своего рода обман, я знаю, но переход из '/etc/localtime' не работает для вас? Например:

>>>  import os
>>> '/'.join(os.readlink('/etc/localtime').split('/')[-2:])
'Australia/Sydney'

Надеюсь, что это поможет.

Редактировать: мне понравилась идея @ A.H., в случае, если '/etc/localtime' не является символической ссылкой. Перевод этого в Python:

#!/usr/bin/env python

from hashlib import sha224
import os

def get_current_olsonname():
    tzfile = open('/etc/localtime')
    tzfile_digest = sha224(tzfile.read()).hexdigest()
    tzfile.close()

    for root, dirs, filenames in os.walk("/usr/share/zoneinfo/"):
        for filename in filenames:
            fullname = os.path.join(root, filename)
            f = open(fullname)
            digest = sha224(f.read()).hexdigest()
            if digest == tzfile_digest:
                return '/'.join((fullname.split('/'))[-2:])
            f.close()
        return None

if __name__ == '__main__':
    print get_current_olsonname()
15
ответ дан Matt Joiner 20 August 2018 в 15:51
поделиться
  • 1
    Он работает, когда / etc / localtime является символической ссылкой. В большинстве случаев это не так. – Matt Joiner 20 October 2011 в 21:51
  • 2
    Это работает на удивление хорошо. Интересно, что произойдет, если zoneinfo был обновлен, но /etc/localtime не был. Кроме того, я рекомендую немедленно переключиться на 4-сегментный отступ вместо вкладок (или 8 пробелов). – Matt Joiner 2 December 2011 в 04:34
  • 3
    Ну, это было 8 пробелов ... Об зонинфо, я думаю, ваша система будет tz-less, без / etc / locatime, не так ли? – tcurvelo 2 December 2011 в 17:22
  • 4
    Я не имел в виду, если обновляются файлы zoneinfo, а / etc / localtime не является символической ссылкой. У вас может быть местное время, которое больше не соответствует ни одному файлу zoneinfo. – Matt Joiner 3 December 2011 в 09:30
  • 5
    В моей системе Ubuntu это, к сожалению, возвращает zoneinfo / localtime. – Matt Joiner 3 December 2011 в 09:40

Установить pytz

import pytz
import time
#import locale
import urllib2

yourOlsonTZ = None
#yourCountryCode = locale.getdefaultlocale()[0].split('_')[1]
yourCountryCode = urllib2.urlopen('http://api.hostip.info/country.php').read()

for olsonTZ in [pytz.timezone(olsonTZ) for olsonTZ in pytz.all_timezones]:
    if (olsonTZ._tzname in time.tzname) and (str(olsonTZ) in pytz.country_timezones[yourCountryCode]):
        yourOlsonTZ = olsonTZ
        break

print yourOlsonTZ

Этот код будет взломать наилучшую догадку в вашем часовом поясе Olson, основанный как на вашем имени часового пояса (как в соответствии с модулем time Python ) и ваш код страны (в соответствии с модулем locale Python проект hostip.info , который ссылается на ваш IP-адрес и соответствующим образом привязывает вас к геолокации).

Например, просто совпадение с именами Timzone может привести к America/Moncton, America/Montreal или America/New_York для EST (GMT-5). Однако, если ваша страна является США, она ограничит ответ на America/New_York.

Однако, если ваша страна - Канада, сценарий будет просто по умолчанию высшим канадским результатом (America/Moncton). Если есть способ доработать это, пожалуйста, оставляйте предложения в комментариях.

6
ответ дан Patrick Perini 20 August 2018 в 15:51
поделиться
  • 1
    Можете ли вы переделать определение кода страны, чтобы получить это значение откуда-то более надежным? В Австралии не редкость иметь en_US, несмотря на то, что существует en_AU. Кроме того, мое имя tz 'EST', поэтому ваш алгоритм дает мне America/New_York, но я нахожусь в Australia/Sydney. – Matt Joiner 2 December 2011 в 04:30
  • 2
    Работаю над этим. Могу ли я использовать веб-доступ? – Patrick Perini 2 December 2011 в 05:36
  • 3
    Нет, вы не можете ... – Matt Joiner 3 December 2011 в 09:38
  • 4
    hostip.info больше не доступно, попробуйте ipdata.co – Jonathan 5 September 2017 в 06:08

Я изменил сценарий tcurvelo, чтобы найти правильную форму часового пояса (Continent /..../ City), в большинстве случаев, но вернуть все из них, если не удалось

#!/usr/bin/env python

from hashlib import sha224
import os
from os import listdir
from os.path import join, isfile, isdir

infoDir = '/usr/share/zoneinfo/'

def get_current_olsonname():
    result = []
    tzfile_digest = sha224(open('/etc/localtime').read()).hexdigest()

    test_match = lambda filepath: sha224(open(filepath).read()).hexdigest() == tzfile_digest

    def walk_over(dirpath):
        for root, dirs, filenames in os.walk(dirpath):
            for fname in filenames:
                fpath = join(root, fname)
                if test_match(fpath):
                    result.append(tuple(root.split('/')[4:]+[fname]))

    for dname in listdir(infoDir):
        if dname in ('posix', 'right', 'SystemV', 'Etc'):
            continue
        dpath = join(infoDir, dname)
        if not isdir(dpath):
            continue
        walk_over(dpath)

    if not result:
        walk_over(join(infoDir))

    return result


if __name__ == '__main__':
    print get_current_olsonname()
0
ответ дан saeedgnu 20 August 2018 в 15:51
поделиться

Вот еще одна возможность, используя PyICU ; который работает для моих целей:

>>> from PyICU import ICUtzinfo
>>> from datetime import datetime
>>> datetime(2012, 1, 1, 12, 30, 18).replace(tzinfo=ICUtzinfo.getDefault()).isoformat()
'2012-01-01T12:30:18-05:00'
>>> datetime(2012, 6, 1, 12, 30, 18).replace(tzinfo=ICUtzinfo.getDefault()).isoformat()
'2012-06-01T12:30:18-04:00'

Здесь он интерпретирует niave datetimes (как будет возвращен запросом базы данных) в локальном часовом поясе.

1
ответ дан SingleNegationElimination 20 August 2018 в 15:51
поделиться
  • 1
    Что-то не так с ICU, что людям не нравится ответ? – saeedgnu 30 July 2013 в 01:31

Одна из проблем заключается в том, что существует несколько «симпатичных имен», таких как «Австралия / Сидней», которые указывают на один и тот же часовой пояс (например, CST).

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

например: для Австралии существует 5 часовых поясов, но больше идентификаторов часовых поясов:

     "Australia/Lord_Howe", "Australia/Hobart", "Australia/Currie", 
     "Australia/Melbourne", "Australia/Sydney", "Australia/Broken_Hill", 
     "Australia/Brisbane", "Australia/Lindeman", "Australia/Adelaide", 
     "Australia/Darwin", "Australia/Perth", "Australia/Eucla"

вы должны проверить, есть ли библиотека, которая обертывает TZinfo, для обработки API часового пояса.

, например: для Python, проверьте библиотеку pytz:

http://pytz.sourceforge.net/

и

http://pypi.python.org/pypi/pytz/

в Python вы можете сделать:

from pytz import timezone
import pytz

In [56]: pytz.country_timezones('AU')
Out[56]: 
[u'Australia/Lord_Howe',
 u'Australia/Hobart',
 u'Australia/Currie',
 u'Australia/Melbourne',
 u'Australia/Sydney',
 u'Australia/Broken_Hill',
 u'Australia/Brisbane',
 u'Australia/Lindeman',
 u'Australia/Adelaide',
 u'Australia/Darwin',
 u'Australia/Perth',
 u'Australia/Eucla']

, но API для Python кажется довольно ограниченным, например он, похоже, не имеет вызова типа Ruby all_linked_zone_names - который может найти все имена синонимов для данного часового пояса.

13
ответ дан Tilo 20 August 2018 в 15:51
поделиться
  • 1
    Я согласен, я думаю, что это означало, что пользователи могут устанавливать свой часовой пояс с меньшими проблемами (например, не зная их смещения UTC). – Mike 6 November 2011 в 09:06
  • 2
    @Tilo: Баунти требует алгоритма для создания этого списка имен часовых поясов. – Matt Joiner 2 December 2011 в 04:26
  • 3
    Легко в Ruby (я добавил ответ для Ruby ниже) ... пожалуйста, проверьте API pytz, как сделать то же самое с Python. – Tilo 2 December 2011 в 08:18

Этот проект JavaScript пытается решить ту же проблему на стороне клиента. Он работает, играя «двадцать вопросов» с языком, запрашивая смещение UTC в определенные прошлые времена (чтобы проверить границы летнего времени и т. Д.) И используя эти результаты, чтобы определить, что должно быть местным часовым поясом. К сожалению, я не знаю какого-либо эквивалентного пакета Python, поэтому, если бы кто-то захотел использовать это решение, его пришлось бы портировать на Python.

Хотя эта формула требует обновления каждый раз (в худшем случае) базы данных TZ обновляется, комбинация этого алгоритма и решение, предложенное Anurag Uniyal (сохраняющее только возможности, возвращенные обоими методами), звучит для меня как самый верный способ вычислить эффективный местный часовой пояс. До тех пор, пока существует некоторая разница между UTC-смещением по меньшей мере одного локального времени в любых двух часовых поясах, такая система может правильно выбирать между ними.

-1
ответ дан wberry 20 August 2018 в 15:51
поделиться
  • 1
    Хотя эта ссылка может ответить на вопрос, лучше включить здесь основные части ответа и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - Из обзора – CJ Dennis 18 May 2018 в 03:40
  • 2
    Два абзаца объяснения - это ответ только для ссылок? – wberry 20 May 2018 в 21:42
  • 3
    Я мог бы выбрать «Это комментарий и не отвечает на вопрос. Когда у вас будет достаточно репутации, вы сможете прокомментировать вопрос. & Quot; Тем не менее, у вас более 10 000 представителей, поэтому они чувствовали себя снисходительными. – CJ Dennis 20 May 2018 в 21:49
  • 4
    Я думаю, что он отлично отвечает на вопрос, иначе я бы не потратил впустую свое время. Учитывая смещение UTC ключевых прошлых дат и времени в качестве подсказок к вашему истинному языку, это подход, который не предлагается никаким другим ответом здесь. Неужели вы не ожидаете, что я буду дублировать точный алгоритм в моем ответе? – wberry 20 May 2018 в 22:18
  • 5
    Если «Этот проект JavaScript» перестает существовать, ваш ответ будет почти бесполезным. Не совсем ясно, как сравнение любого количества дат UTC может дать результат Australia/Sydney. – CJ Dennis 20 May 2018 в 22:48
Другие вопросы по тегам:

Похожие вопросы: