Do you want to pick up from where you left of?
Take me there

Дата и время

Работа с временем в Elixir.

Время

В Elixir есть несколько модулей для работы со временем. Начнём с получения текущего времени:

iex> Time.utc_now
~T[19:39:31.056226]

Обратите внимание на строковую метку, через которую также можно создать структуру Time:

iex> ~T[19:39:31.056226]
~T[19:39:31.056226]

Вы можете узнать больше о строковых метках в уроке о строковых метках. Можно легко получить части этой структуры:

iex> t = ~T[19:39:31.056226]
~T[19:39:31.056226]
iex> t.hour
19
iex> t.minute
39
iex> t.day
** (KeyError) key :day not found in: ~T[19:39:31.056226]

Но тут есть загвоздка: как вы могли заметить, в этой структуре есть только время в пределах суток, поэтому нет числа/месяца/года.

Дата

В отличие от Time, структура Date содержит только текущую дату, без какой-либо информации о времени.

iex> Date.utc_today
~D[2028-10-21]

Кроме этого, есть полезные функции для работы с датами:

iex> {:ok, date} = Date.new(2020, 12, 12)
{:ok, ~D[2020-12-12]}
iex> Date.day_of_week date
6
iex> Date.leap_year? date
true

day_of_week/1 определяет день недели указанной даты. В данном случае это суббота. leap_year?/1 определяет, является ли год високосным. Остальные функции вы можете найти в документации.

NaiveDateTime

В Elixir существует два вида структур, содержащих и время, и дату. Первая - NaiveDateTime. Её недостаток - отсутствие поддержки часовых поясов:

iex> NaiveDateTime.utc_now
~N[2022-01-21 19:55:10.008965]

Но она содержит как время, так и дату, так что можете попробовать добавить времени, к примеру:

iex> NaiveDateTime.add(~N[2018-10-01 00:00:14], 30)
~N[2018-10-01 00:00:44]

DateTime

Вторая, как вы уже могли догадаться из названия раздела, называется DateTime. У неё нет ограничений, упомянутых в NaiveDateTime: она хранит как время, так и дату, а также поддерживает часовые пояса. Но будьте осторожны с часовыми поясами. Как сказано в официальной документации:

Многие функции в этом модуле требуют базы данных часовых поясов. По умолчанию они используют базу данных часовых поясов возвращаемую функцией Calendar.get_time_zone_database/0, которая по умолчанию равна Calendar.UTCOnlyTimeZoneDatabase, которая обрабатывает только “Etc/UTC” даты и возвращает {:error, :utc_only_time_zone_database} для любого другого часового пояса.

Также обратите внимание, что можно создать DateTime из NaiveDateTime, только передав часовой пояс:

iex> DateTime.from_naive(~N[2016-05-24 13:26:08.003], "Etc/UTC")
{:ok, #DateTime<2016-05-24 13:26:08.003Z>}

Работаем с часовыми поясами

Как мы отмечали в предыдущей главе, по умолчанию в Elixir нет данных о часовых поясах. Чтобы решить эту проблему, нам нужно установить и настроить пакет tzdata. После его установки вы должны глобально настроить Elixir на использование Tzdata в качестве базы данных часовых поясов:

config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase

Давайте теперь попробуем создать время в часовом поясе Парижа и преобразовать его в Нью-Йоркское время:

iex> paris_datetime = DateTime.from_naive!(~N[2019-01-01 12:00:00], "Europe/Paris")
#DateTime<2019-01-01 12:00:00+01:00 CET Europe/Paris>
iex> {:ok, ny_datetime} = DateTime.shift_zone(paris_datetime, "America/New_York")
{:ok, #DateTime<2019-01-01 06:00:00-05:00 EST America/New_York>}
iex> ny_datetime
#DateTime<2019-01-01 06:00:00-05:00 EST America/New_York>

Как видите, время изменилось с 12:00 по парижскому времени до 6:00, что правильно - разница во времени между двумя городами составляет 6 часов.

Вот и всё! Если вы хотите попробовать другие дополнительные функции, загляните в документацию Time, Date, DateTime и NaiveDateTime Также рекомендуем изучить Timex и Calendar - мощные библиотеки для работы с временем в Elixir.

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!