Как узнать часовой пояс python
Перейти к содержимому

Как узнать часовой пояс python

  • автор:

«Eppur si muove!»* или Работаем с таймзонами в Python

На нашей планете Земля, в одно и то же время, в разных географических точках планеты может быть разное время суток. Это следствие того, что наш мир — вращающийся геоид, а не плоский диск, а что наша Солнечная система имеет только одну звезду — Солнце. Ещё со школы всем известно о часовых поясах, и все мы встречались с их проявлениями в реальной жизни («Московское время – 15 часов, в Петропавловске-Камчатском – полночь», джетлаг при дальних перелётах, и т.д.). К несчастью, часовые пояса всего лишь частично основаны на физических особенностях нашего мира, и при компьютерных вычислениях приходится учитывать другие, порой неожиданные, нюансы.

* «И всё-таки она вертится!» — крылатая фраза, которую якобы произнёс Галилео Галилей, покидая процесс инквизиции после отречения от своего убеждения в том, что Земля вращается вокруг Солнца. В нашем случае, увы, это вращение приводит ко всем этим «замечательным» проблемам с часовыми поясами.

Что общего у этой статьи и Галилео? Да, в общем-то, ничего. Боюсь, что если бы наш мир был центром вселенной, нам всё равно пришлось бы иметь дело с таймзонами. Будем считать заголовок моей оплошностью, которую я уже не могу исправить (хотя я могу).

Что такое «Часовой пояс»?

Какой у вас часовой пояс? Если вы ответите «UTC+3» — это будет правильным ответом только на текущий момент времени, но в целом это заявление некорректно. Если вы посмотрите на базу данных часовых поясов, то увидите, к примеру, что Берлин и Вена, несмотря на смещение «UTC+1», имеют разные часовые пояса («Europe/Berlin» и «Europe/Vienna»). Почему так? Причина в том, что они имели разное летнее время (DST) в разные периоды истории. Даже если сегодня эти две страны и эти два города имеют одинаковые правила DST, сто лет назад это было не так. Например, и в Австрии и в Германии в разные периоды времени не было перехода на летнее время: в Австрии с 1920 года, а в Германии с 1918. Во время Второй мировой войны обе страны имели одинаковые правила DST (что не удивительно), однако после её окончания снова рассинхронизировались. Германия отменила переход на летнее время в 1949 и ввела его снова в 1979, Австрия же отменила DST в 1948 и ввела его снова в 1980. Самое же худшее состоит в том, что они даже не согласовали одинаковую дату перехода на летнее время.

И так происходит по всему миру. Для компьютерных вычислений, переход на летнее время — огромная проблема, ведь мы предполагаем, что время имеет непрерывный мотононный ход. С переходом на летнее время у нас каждый год есть час, который повторяется дважды, и есть час, который мы просто пропускаем. Если при записи в лог вы указываете локальное время, у вас можем нарушится порядок строк лога при сортировке.

Цитата из документации pytz:

Но в таймзонах хранятся не только правила перехода на летнее время. Некоторые страны меняют часовые пояса, иногда даже без изменения DST. Так, например, в 1915 году Варшава перешла на Центральноевропейское время. В результате в полночь 5 августа 1915 года часы были переведены на 24 минуты назад (при этом в Варшаве действовало летнее время).
Вообще, с часовыми поясами творится ещё больший ад. Есть как минимум одна страна, таймзона которой была различна в течение дня из-за синхронизации времени 0:00 с временем восхода Солнца.

Где же здравый смысл?

Здравый смысл есть и он называется Всемирное координированное время (UTC). UTC — это таймзона без перехода на летнее время и без каких бы то ни было изменений в прошлом. Однако по причине того, что наша Земля — вращающийся геоид и в мире есть вещи, которые мы не можем контролировать, существует проблема корректировочных секунд (leap seconds). Будет ли UTC учитывать корректировочные секунды (которые нерегулярны и поэтому их достаточно проблематично учитывать при вычислениях), или не будет (тогда каждая таймзона будет иметь разницу в несколько секунд с UTC), — насколько мне известно, ещё не решено.

Несмотря на это, прямо сейчас UTC — самый безопасный вариант. Из UTC вы можете сконвертировать время в локальное для любого часового пояса. Обратное преобразование, учитывая вышесказанное, невозможно.

Итак, вот главное практическое правило, которое никогда вас не подведёт:

В чём проблема?

Вообще, на этом статья должна была бы закончиться. Но к несчастью, есть пара вещей, которые необходимо держать в памяти, когда вы программируете на Python. Это наследие архитектурных решений тех давних времён, когда никто не думал о практическом применении языка. Мотивация имела значение, здравый смысл — нет.

  1. Модуль datetime не должен хранить информацию о таймзонах, потому что таймзоны меняются слишком часто.
  2. С другой стороны, модуль datetime должен давать возможность добавлять в себя информацию о таймзоне (tzinfo).
  3. В модуле datetime должны быть реализованы следующие объекты: date, time, date+time, timedelta.

Если закрыть глаза на тот ужасный API, с помощью которого вам приходится добавлять информация о таймзоне к объекту datetime, всё равно остаются проблемы. Когда вы работаете с объектами datetime в Питоне, вам рано или поздно придётся добавлять или удалять tzinfo во всех местах вашей программы.

Другая проблема состоит в том, что у вас есть два способа создать объект datetime с текущим временем в Python:

Один возвращает время в UTC, другой — локальное время. Однако объект datetime не скажет вам, что такое «локальное время» (потому что он не имеет информации о таймзоне, по крайней мере до версии Python 3.3), и нет никакого способа узнать, который из этих объектов хранит время в UTC.

Если вы конвертируете UNIX timestamp в объект datetime, вам так же следует быть осторожным при использовании метода datetime.datetime.utcfromtimestamp, потому что он принимает timestamp в локальном времени.

Библиотека datetime так же предоставляет объекты date и time, в которые абсолютно бесполезно добавлять tzinfo. Объект time не может быть переведён в другую таймзону, поскольку для этого нужно знать дату. Объект date вообще имеет смысл только для локальной таймзоны, потому что «сегодня» для меня может быть «вчера» или «завтра» для вас — скажем спасибо чудесному миру часовых поясов.

Так каковы рекомендации специалистов?

Теперь мы знаем, кто виноват. Но что делать? Если мы проигнорируем теоретические проблемы, проявляющиеся только в случае работы с историческими датами в прошлом, то вот вам ряд рекомендаций. На тот случай, если вам приходится работать с историческими датами, есть альтернативный модуль mxDateTime, достаточно качественно спроектированный и даже поддерживающий различные календари (Григорианский и Юлианский).

Используйте UTC внутри программы

Если вам нужно получить текущее время, всегда используйте datetime.datetime.utcnow(). Если вы получаете локальное время от пользователя, всегда тут же преобразовывайте его в UTC. Если однозначного преобразования сделать не получается — сообщайте об этом пользователю, не пытайтесь угадать его время вслепую. Во время перехода на летнее время и обратно, мой iPhone несколько раз не смог правильно перевести время. Я же знаю, когда это нужно сделать, поскольку мне приходится переводить стрелочные часы.

Никогда не используете время с часовым поясом

  1. Внутри программы всегда используйте объекты datetime без tzinfo с временем по UTC.
  2. Когда вы взаимодействуете с пользователем, всегда конвертируйте его локальное время UTC и обратно.

Другая причина не использовать время с таймзоной заключается в том, что объект tzinfo очень специфичен и сильно зависит от своей реализации. Не существует стандартного способа передавать информацию о таймзоне (за исключением, пожалуй, таймзоны UTC) в другие языки, по HTTP и т.д. К тому же объекты datetime с информацией о таймзоне, зачастую, становятся слишком огромными при сериализации с помощью модуля pickle, или их даже невозможно бывает сериализовать (это зависит от реализации объекта tzinfo).

Преобразования для форматирования

Если вам нужно показать время в таймзоне пользователя, возьмите объект datetime с временем по UTC, добавьте в него таймзону UTC, преобразуйте время в локальное время пользователя и отформатируйте его. Не используйте преобразование таймзоны методами tzinfo, ибо они работают некорректно, используйте pytz. Потом переведите время в «наивное» путём отбрасывания смещения таймзоны из получившегося объекта datetime, который вы создали для форматирования и продолжайте жить счастливо.

Бонус от переводчика для тех, кто дочитал до конца:

Шикарное видео от Tom Scott про таймзоны:

А в следующей своей статье я напишу, где автор неправ, почему он ошибается и как же всё-таки нужно делать правильно.

Working With TimeZones in Python

In this tutorial, we will learn how to work with timezone in Python.

After reading this article, you’ll learn:

  • Handling of timezone by creating a timezone aware date and time.
  • How to get the current time in a different timezone
  • Get the current timezone name, UTC offset, and DST offset if DST is in effect
  • How to convert UTC Datetime to a specific timezone
  • Convert time from one timezone to another
  • Mathematical operations on two timezone-aware and timezone naive objects
  • Learn the tzinfo implementation modules namely pytz, ZoneInfo, and their methods.

Table of contents

What is timezone in Python?

A time zone represents the standardized time depending on which part of the world is being considered.

In simple terms, timezone refers to the local time of a region. UTC (Coordinated Universal Time) is the astronomical time based on earth’s rotation, is the standard against which the world’s region-based time is coordinated.

Note: UTC – Coordinated Universal Time is the common time standard across the world. So, in Python, to work with the timezone without any issues, it is recommended to use the UTC as your base timezone

For example, CT(Central Time) in North and South America is either 5 or 6 hours behind and represented as UTC-5 or UTC-6 based on the Day Light Saving. Below are a few examples.

UTC Offset Locations Name Location
UTC +9 Japan, South Korea, and 5 more JST Tokyo
UTC +5:30 India IST India
UTC +1 The United Kingdom and 20 more BST London
UTC -10 Hawaii/USA and 2 more HST Honolulu

TimeZones

Python provides the datetime.tzinfo abstract base class which provides methods to handle timezone. But this class is an abstract base class and should not be instantiated directly. We need to define a subclass of tzinfo to capture information about a particular time zone.

The pytz library has implemented a timezone class for handling arbitrary fixed offsets from UTC and timezones. This library allows accurate and cross-platform timezone calculations and also solves the issue of ambiguous times at the end of daylight saving time.

pytz is a concrete implementation of the abstract base class tzinfo and is used to create timezone-aware datetime objects.

For example, The datetime.now() function returns the current local date-time without any timezone information. Using the pytz library, we can pass the timezone name to this function to get the current datetime in the given timezone.

We’ll use the following attributes and methods of the pytz module to work with timezone in Python.

  • pytz.utc : Get the standard UTC timezone
  • pytz.timezone(‘region’) : Create the timezone object of a particular region
  • pytz.astimezone() : Convert the time of a particular time zone into another time zone

Create Timezone Aware Datetime Object

In Python, a date object can be mentioned with or without timezones. Based on that, an object is known as Naive or Aware. A date object, by default, is naive. A datetime or time object is aware if it holds the timezone(tz) value.

Follow the below steps to create a timezone aware Datetime Object in Python: –

  • Install pytz module if not installed using the pip install pytz command.
  • Use the pytz.timezone(‘region_name’) function to create the timezone object
  • Use the datetime.now(timezone_obj) or datetime.datetime(‘timezone’) function to create the timezone aware current datetime.

Create timezone aware datetime

Example:

Output:

  • To get the UTC time we used the pytz.utc as a parameter to datetime.now() function. The offset at the end is +00:00 which is the standrad UTC offset.
  • To get the CDT datetime, we used the ‘US/Central’ region to create a timezone. The offset at the end is -05:00 is the UTC offset of the CDT region

Refer to list all timezones in Python if you don’t know the exact name of the timezone to create a date and time in the right timezone.

To make the old/existing datetime timezone aware, use the following code.

Note: The datetime.replace() method return the new datetime instance.

Format UTC DateTime to Get the timezone name

Extract the timezone name from UTC DateTime using the DateTime formatting in Python. Use the %Z directive to get the timezone name.

Note: IST is the timezone name

Create TimeZone Aware Datetime Object Using timezone class

Let’s see how create a timezone aware datetime object without pytz.

The datetime modules have the timezone class, which in turn is the subclass of the abstract base class tzinfo . Each instance created of the timezone class represents the offset of the timezone from the Coordinated Universal Time (UTC).

We can create an UTC-aware datetime object by assigning the timezone.utc

Syntax:

Here offset represents the difference between the local time and the UTC (Coordinated Universal Time). It can be a time delta object ranging from hours=-24 to +24.

Example:

Note: we are setting the UTC offset using the timedelta class timedelta(hours=+9)

Get Current Time in Different Timezone

Using the pytz module we can get the current date and time of any timezone.

Syntax:

Steps:

  • Use the pytz.timezone(‘region_name’) function to create the timezone object
  • Use datetime.now(timezone_obj) function to get the current datetime of the given timezone.

Note: UTC – Coordinated Universal Time is the common time standard across the world. So, to work with the timezone without any issues, it is recommended to use the UTC as your base timezone.

In this example, we’ll see how to get the current datetime in the following timezones

USA: Get current Date and Time in the following TimeZones of United States

Output:

Other TimeZones

Output:

Also, see: Convert between timezones

Get TimeZone Information Using tzinfo

The datetime.tzinfo is an abstract base class containing information about the date or time object passed to them.

The tzinfo generally contains the following information: –

  • The time zone name of a Datetime
  • Offset from the UTC (Coordinated Universal Time)
  • The DST(Daylight saving).

The tzinfo class provides the following method to get the timezone information: –

  • tzinfo.tzname(dt) : Returns the time zone name corresponding to the datetime object dt . This method returns the name that is used while creating the timezone object
  • tzinfo.utcoffset(dt) : This method returns the total offset from the UTC which should be a timedelta object. The values of the timedelta is positive if it is east of UTC and negative for the west of UTC. The total offset includes both timezone and the DST(Day light savings) values. The range of the timedelta is therfore between -timedelta(hours=24) to timedelta(hours=24)
  • tzinfo.dst(dt) : This method returns dst offset in the zones where dst is in effect. In other cases it will return only timedelta(0) . The dst information is already part of the the utcoffset therefore the t z.utcoffset(dt) — tz.dst(dt) should return the standard offset of the timezone irrespective of the date and time but only on the geographic location.

Example:

Our code produced the following information:

The datetime modules have the timezone class, which in turn is the subclass of the abstract base class tzinfo

Converting Between Timezones

Use the datetime.astimezone() method to convert the datetime from one timezone to another. This method uses an instance of the datetime object and returns a new datetime of a given timezone.

Output:

Working with Local Timezones

Note: To work with the timezone without any issues, it is recommended to use the UTC as your base timezone not a local time.

As already mentioned, we can convert a naive datetime to an aware datetime instance with a timezone value set to a local standardized value.

We can do it with one of the pytz methods called localize () .This method is used to convert a naive to local time. It accepts the two arguments, namely the datetime object to localize and an optional is_dst flag.

This flag is set to true if we want to localize and the daylight saving information and false if we want only the standard offset time and false otherwise.

As mentioned above the tzinfo has a method called dst() which will return the Daylight Saving Time(DST) information if the flag is set to true.

Let us see an example to show how we can set a local time zone and get the DST information.

Output

Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.

About Vishal

Founder of PYnative.com I am a Python developer and I love to write articles to help developers. Follow me on Twitter. All the best for your future Python endeavors!

Related Tutorial Topics:

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

Текущая дата и время в Python

Время и дата играют важнейшую роль при решении определенных задач в программировании. Разработчику на Python приходится нередко использовать точные значения текущей (current) даты, к примеру, при сохранении информации в базе данных, вычислениях, регистрации, обеспечении доступа и т. д. В этой статье пойдет разговор о том, как узнать текущие временные значения с помощью модуля datetime. Вдобавок к этому, читатель узнает о временных настройках для разных часовых поясов и преобразовании объектов datetime в метки времени Unix.

Получаем текущую дату и время

Datetime включает в себя разные классы, позволяющие получать нужные временные данные:

  1. datetime.date: день, месяц и год;
  2. datetime.time: время в часах, минутах, секундах, а также микросекундах. Тут дата значения не имеет;
  3. datetime.datetime: здесь хранятся атрибуты date и time.

Для примера можно вывести в терминал текущую (current) дату и время. Можно воспользоваться объектом datetime.datetime — из него довольно просто извлекаются объекты date и time. Сначала следует импортировать требуемый модуль:

from datetime import datetime

Да, это выглядит странновато, т. к. речь идет о получении класса datetime из модуля datetime, однако это 2 разные вещи. Далее следует воспользоваться функцией now() — она позволит получить объект с текущим временем и датой.

from datetime import datetime

Набрав код выше, вы увидите на экране следующее (в вашем случае вывод изменится, ведь минуты не стоят на месте):

Что произошло? Функция now() отобразила объект, причем с датой и временем создания этого самого объекта. В результате была выведена соответствующая строка. Однако никто не мешает получить временные атрибуты отдельно:

Таким образом, метод now() вполне годится для получения текущей даты и времени. Но что делать, если надо получить лишь дату?

Работа с датой current

Существуют 2 способа получения текущей даты. Первый выводит нужные данные из объекта datetime посредством метода date() :

Во втором применяется метод today() класса date:

Класс datetime.date позволяет получать календарную дату. Также следует добавить, что его атрибуты (year, month, day) бывают доступны и отдельно, как в примере с datetime.

Тут все понятно и просто. Но есть нюанс: если надо получить день недели, прописывают current_date.weekday()+1 . Дело в том, что нумерация дней недели начинается с нуля, то есть понедельник — это 0, вторник — 1, среда — 2 и так далее. Если такое положение вещей устраивает, +1 можно и не добавлять.

А как поступить, если надо отобразить текущее время отдельно от даты?

Работаем с текущим временем

Текущее время от объекта datetime получают посредством метода time() . Вот как это выглядит:

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

Важно отметить, что есть возможность получить временные данные и с учетом нужного часового пояса (timezone). Как и что используется, поговорим ниже.

Другой часовой пояс: временные зоны (timezones)

Метод now() принимает в Python временную зону в качестве аргумента, так что объект datetime генерируется соответствующим образом.

Для получения информации с учетом часового пояса необходимо задействовать библиотеку pytz (если ее нет, потребуется инсталляция, для чего подойдет команда pip3 install pytz ).

Так как я нахожусь в Минске, давайте получим текущие временные значения (times) именно для Минска:

Строка в коде minsk_current_datetime является объектом datetime, то есть все то же самое, что и ранее, но уже в полном соответствии с часовым поясом Республики Беларусь.

Когда надо узнать время в UTC, тоже пригодится модуль pytz:

Получить время UTC можно и без модуля pytz, т. к. datetime имеет полезное свойство timezone. Что же, давайте задействуем свойство timezone:

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

Преобразование временных меток

Также может быть очень полезным преобразовывать время в один из самых широко применяемых форматов в вычислениях. Речь идет о временных метках Unix.

Доподлинно известно, что компьютерные системы измеряют время не так, как люди. Здесь за основу берется число секунд, которые прошли с начала Unix-эпохи, то есть с 00:00:00 UTC 1.01.1979. Базы данных, протоколы и приложения обычно задействуют временную метку.

Для ее получения в «Питоне» пригодится модуль time, следовательно, первая строка будет import time :

Функция time.time() возвращает пользователю число с плавающей запятой и с временной меткой Unix.

На этом все. Очень надеемся, что вы получили некоторое представление об использовании встроенных Python-библиотек и модулей, необходимых для отображения временных значений.

Get time zone information of the system in Python?

I want to get the default timezone (PST) of my system from Python. What’s the best way to do that? I’d like to avoid forking another process.

aliteralmind's user avatar

9 Answers 9

This should work:

time.tzname returns a tuple of two strings: The first is the name of the local non-DST timezone, the second is the name of the local DST timezone.

Example return: (‘MST’, ‘MDT’)

caffreyd's user avatar

Gives a UTC offset like in ThomasH’s answer, but takes daylight savings into account.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *