Spec-Zone.ru › Elixir 1.14

DateTime

Реализация DateTime с часовым поясом.

Этот DateTime можно рассматривать как снимок даты и времени в заданном часовом поясе. Для таких целей он также включает в себя как смещения UTC, так и стандартные смещения, а также поле сокращения зоны, используемое исключительно для целей форматирования. Обратите внимание, что будущие DateTime не обязательно гарантированы, так как часовые пояса могут измениться в любое время в будущем из-за геополитических причин. Для получения дополнительной информации см. раздел «DateTime как снимки».

Помните, что сравнения в Elixir с использованием ==/2, >/2, </2 и аналогичными функциями структурные и основаны на полях структуры DateTime. Для правильного сравнения DateTime используйте функцию compare/2. Наличие функции compare/2 в этом модуле также позволяет использовать функции Enum.min/2 и Enum.max/2 для получения минимального и максимального DateTime из перечисления Enum. Например:

iex> Enum.min([~U[2022-01-12 00:01:00.00Z], ~U[2021-01-12 00:01:00.00Z]], DateTime)
~U[2021-01-12 00:01:00.00Z]

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

База данных часовых поясов

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

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

  • tz
  • tzdata
  • zoneinfo — рекомендуется для встроенных устройств

Для их использования необходимо убедиться, что она добавлена в качестве зависимости в mix.exs. Затем ее можно настроить либо через конфигурацию:

config :elixir, :time_zone_database, Tz.TimeZoneDatabase

или вызвав Calendar.put_time_zone_database/1:

Calendar.put_time_zone_database(Tz.TimeZoneDatabase)

См. правильные имена в инструкциях по установке библиотеки.

DateTime как снимки

В первом разделе мы описали DateTime как «снимок даты и времени в заданном часовом поясе». Давайте рассмотрим пример, чтобы лучше понять это.

Представьте, что кто-то в Польше хочет назначить встречу с кем-то в Бразилии в следующем году. Встреча состоится в 2:30 утра по польскому времени. В какое время встреча состоится в Бразилии?

Вы можете проконсультироваться с базой данных часовых поясов сегодня, за год до этого, используя API в этом модуле, и она даст вам ответ, который действителен прямо сейчас. Однако этот ответ может не быть действительным в будущем. Почему? Потому что и Бразилия, и Польша могут изменить свои правила часовых поясов, что в конечном итоге повлияет на результат. Например, страна может выбрать включение или отказ от «летнего времени», что является процессом, в результате которого время на часах корректируется на один час вперёд или назад один раз в год. Когда правила меняются, точный момент, когда 2:30 утра польского времени будет в Бразилии, может измениться.

Другими словами, при работе с будущими DateTime нет гарантии, что полученные результаты всегда будут корректными, пока событие не произойдёт. Поэтому, когда вы запрашиваете будущее время, полученные ответы являются снимком, отражающим текущее состояние правил часовых поясов. Для DateTime в прошлом это не проблема, потому что правила часовых поясов не меняются для прошлых событий.

Что еще хуже, может случиться так, что 2:30 утра по польскому времени вообще не существует или это неоднозначно. Если определённый часовой пояс использует «летнее время», они переведут свои часы вперёд один раз в год. Когда это происходит, целого часа не существует. Затем, когда они переведут часы назад, определённый час повторится дважды. Таким образом, если вы хотите назначить встречу, когда произойдёт такое смещение назад, вам нужно будет чётко указать, о каком 2:30 утра идёт речь. Приложения, чувствительные к дате и времени, должны учитывать эти сценарии и правильно сообщать об этом пользователям.

Хорошая новость: Elixir содержит все необходимые инструменты для решения этих проблем. База данных часовых поясов по умолчанию, используемая Elixir, Calendar.UTCOnlyTimeZoneDatabase, работает только с UTC, который не сталкивается с этими проблемами. После добавления надлежащей базы данных часовых поясов функции в этом модуле запросят базу данных и вернут соответствующую информацию. Например, посмотрите, как DateTime.new/4 возвращает разные результаты в зависимости от описанных в этом разделе сценариев.

Краткое описание

Типы

t()

Функции

add(datetime, amount_to_add, unit \\ :second, time_zone_database \\ Calendar.get_time_zone_database())

Добавляет указанное количество времени к DateTime.

compare(datetime1, datetime2)

Сравнивает две структуры datetime.

convert(datetime, calendar)

Преобразует заданную datetime из одного календаря в другой.

convert!(datetime, calendar)

Преобразует заданную datetime из одного календаря в другой.

diff(datetime1, datetime2, unit \\ :second)

Вычитает datetime2 из datetime1.

from_gregorian_seconds(seconds, arg \\ {0, 0}, calendar \\ Calendar.ISO)

Преобразует количество григорианских секунд в структуру DateTime.

from_iso8601(string, format_or_calendar \\ Calendar.ISO)

Парсит расширенный формат «Дата и время дня», описанный в ISO 8601:2019.

from_iso8601(string, calendar, format)

Преобразует в ISO8601, задавая календарь и режим.

from_naive(naive_datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())

Преобразует заданное NaiveDateTime в DateTime.

from_naive!(naive_datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())

Преобразует заданное NaiveDateTime в DateTime.

from_unix(integer, unit \\ :second, calendar \\ Calendar.ISO)

Преобразует заданное время Unix в DateTime.

from_unix!(integer, unit \\ :second, calendar \\ Calendar.ISO)

Преобразует заданное время Unix в DateTime.

new(date, time, time_zone \\ "Etc/UTC", time_zone_database \\ Calendar.get_time_zone_database())

Создаёт datetime из структур date и time.

new!(date, time, time_zone \\ "Etc/UTC", time_zone_database \\ Calendar.get_time_zone_database())

Создаёт datetime из структур date и time, выбрасывая исключение при ошибках.

now(time_zone, time_zone_database \\ Calendar.get_time_zone_database())

Возвращает текущее datetime в заданном часовом поясе.

now!(time_zone, time_zone_database \\ Calendar.get_time_zone_database())

Возвращает текущее datetime в заданном часовом поясе или выбрасывает исключение при ошибках.

shift_zone(datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())

Изменяет часовой пояс DateTime.

shift_zone!(datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())

Изменяет часовой пояс DateTime или выбрасывает исключение при ошибках.

to_date(datetime)

Преобразует DateTime в Date.

to_gregorian_seconds(datetime)

Преобразует структуру DateTime в количество григорианских секунд и микросекунд.

to_iso8601(datetime, format \\ :extended, offset \\ nil)

Преобразует данное datetime в формат ISO 8601:2019.

to_naive(datetime)

Преобразует данное datetime в NaiveDateTime.

to_string(datetime)

Преобразует данное datetime в строку в соответствии с его календарём.

to_time(datetime)

Преобразует DateTime в Time.

to_unix(datetime, unit \\ :second)

Преобразует данное datetime в время Unix.

truncate(datetime, precision)

Возвращает заданное datetime с микросекундной частью, усечённой до заданной точности (:microsecond, :millisecond или :second).

utc_now(calendar \\ Calendar.ISO)

Возвращает текущее datetime в UTC.

Типы

t()Source

@type t() :: %DateTime{
  calendar: Calendar.calendar(),
  day: Calendar.day(),
  hour: Calendar.hour(),
  microsecond: Calendar.microsecond(),
  minute: Calendar.minute(),
  month: Calendar.month(),
  second: Calendar.second(),
  std_offset: Calendar.std_offset(),
  time_zone: Calendar.time_zone(),
  utc_offset: Calendar.utc_offset(),
  year: Calendar.year(),
  zone_abbr: Calendar.zone_abbr()
}
END_OF_DOCUMENT_MARKER

Функции

add(datetime, amount_to_add, unit \\ :second, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec add(
  Calendar.datetime(),
  integer(),
  :day | :hour | :minute | System.time_unit(),
  Calendar.time_zone_database()
) :: t()

Добавляет заданное количество времени к DateTime.

Принимает amount_to_add в любом unit. unit может быть :day, :hour, :minute, :second или любой точностью до долей секунды из System.time_unit/0. По умолчанию :second. Отрицательные значения сместят время назад.

Эта функция всегда учитывает единицы измерения в соответствии с Calendar.ISO.

Эта функция использует непрерывное представление времени, игнорируя время по часам и изменения часовых поясов. Например, если вы добавите один день, когда есть переходы на летнее/зимнее время, это также изменит время вперед или назад на один час, чтобы общее время составило ровно 24 часа. Аналогично, добавление нескольких секунд к дате и времени непосредственно перед переходом на летнее время может привести к увеличению времени по часам более чем на час.

Хотя это означает, что функция точна с точки зрения прошедшего времени, её результат может быть вводящим в заблуждение в определенных случаях использования. Например, если пользователь запросил встречу каждый день в 15:00, и вы используете эту функцию для вычисления всех будущих встреч, добавляя день за днём, эта функция может изменить время встречи на 14:00 или 16:00, если произойдут изменения в текущем часовом поясе. Вычисление повторяющихся дат и времени в настоящее время не поддерживается стандартной библиотекой Elixir, но доступно в сторонних библиотеках.

Примеры

iex> dt = DateTime.from_naive!(~N[2018-11-15 10:00:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> dt |> DateTime.add(3600, :second, FakeTimeZoneDatabase)
#DateTime<2018-11-15 11:00:00+01:00 CET Europe/Copenhagen>

iex> DateTime.add(~U[2018-11-15 10:00:00Z], 3600, :second)
~U[2018-11-15 11:00:00Z]

При добавлении 3 секунд непосредственно перед переходом на летнее время мы переходим с 1:59:59 до 3:00:02:

iex> dt = DateTime.from_naive!(~N[2019-03-31 01:59:59.123], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> dt |> DateTime.add(3, :second, FakeTimeZoneDatabase)
#DateTime<2019-03-31 03:00:02.123+02:00 CEST Europe/Copenhagen>

При добавлении 1 дня во время перехода на летнее время, час также меняется:

iex> dt = DateTime.from_naive!(~N[2019-03-31 01:00:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> dt |> DateTime.add(1, :day, FakeTimeZoneDatabase)
#DateTime<2019-04-01 02:00:00+02:00 CEST Europe/Copenhagen>

compare(datetime1, datetime2)Source

@spec compare(Calendar.datetime(), Calendar.datetime()) :: :lt | :eq | :gt

Сравнивает две структуры datetime.

Возвращает :gt если первая дата и время позже второй, и :lt в обратном случае. Если две даты и время равны, возвращается :eq.

Обратите внимание, что при сравнении будут учитываться как смещения UTC, так и стандартные смещения.

Примеры

iex> dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                 hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                 utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> dt2 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                 hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                 utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.compare(dt1, dt2)
:gt

convert(datetime, calendar)Source

@spec convert(Calendar.datetime(), Calendar.calendar()) ::
  {:ok, t()} | {:error, :incompatible_calendars}

Преобразует заданную datetime из одного календаря в другой.

Если невозможна однозначная конвертация между календарями (см. Calendar.compatible_calendars?/2), возвращается кортеж {:error, :incompatible_calendars}.

Примеры

Представьте, что кто-то реализовал Calendar.Holocene, календарь, основанный на григорианском календаре, который добавляет ровно 10 000 лет к текущему григорианскому году:

iex> dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                 hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                 utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.convert(dt1, Calendar.Holocene)
{:ok, %DateTime{calendar: Calendar.Holocene, day: 29, hour: 23,
                microsecond: {0, 0}, minute: 0, month: 2, second: 7, std_offset: 0,
                time_zone: "America/Manaus", utc_offset: -14400, year: 12000,
                zone_abbr: "AMT"}}

convert!(datetime, calendar)Source

@spec convert!(Calendar.datetime(), Calendar.calendar()) :: t()

Преобразует заданную datetime из одного календаря в другой.

Если невозможна однозначная конвертация между календарями (см. Calendar.compatible_calendars?/2), возникает исключение ArgumentError.

Примеры

Представьте, что кто-то реализовал Calendar.Holocene, календарь, основанный на григорианском календаре, который добавляет ровно 10 000 лет к текущему григорианскому году:

iex> dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                 hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                 utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.convert!(dt1, Calendar.Holocene)
%DateTime{calendar: Calendar.Holocene, day: 29, hour: 23,
          microsecond: {0, 0}, minute: 0, month: 2, second: 7, std_offset: 0,
          time_zone: "America/Manaus", utc_offset: -14400, year: 12000,
          zone_abbr: "AMT"}

diff(datetime1, datetime2, unit \\ :second)Source

@spec diff(
  Calendar.datetime(),
  Calendar.datetime(),
  :day | :hour | :minute | System.time_unit()
) :: integer()

Вычитает datetime2 из datetime1.

Ответ может быть возвращен в любых :day, :hour, :minute, или любых unit доступных в System.time_unit/0. Единицы измерения измеряются в соответствии с Calendar.ISO и по умолчанию составляют :second.

Дробные результаты не поддерживаются и усекаются.

Примеры

iex> dt1 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                 hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                 utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> dt2 = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                 hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                 utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.diff(dt1, dt2)
18000
iex> DateTime.diff(dt2, dt1)
-18000
iex> DateTime.diff(dt1, dt2, :hour)
5
iex> DateTime.diff(dt2, dt1, :hour)
-5

from_gregorian_seconds(seconds, arg \\ {0, 0}, calendar \\ Calendar.ISO)Source

@spec from_gregorian_seconds(integer(), Calendar.microsecond(), Calendar.calendar()) ::
  t()

Преобразует количество григорианских секунд в структуру DateTime.

Возвращаемая DateTime будет иметь часовой пояс UTC, если вам нужен другой часовой пояс, используйте DateTime.shift_zone/3.

Примеры

iex> DateTime.from_gregorian_seconds(1)
~U[0000-01-01 00:00:01Z]
iex> DateTime.from_gregorian_seconds(63_755_511_991, {5000, 3})
~U[2020-05-01 00:26:31.005Z]
iex> DateTime.from_gregorian_seconds(-1)
~U[-0001-12-31 23:59:59Z]

from_iso8601(string, format_or_calendar \\ Calendar.ISO)Source

Парсит расширенный формат «Дата и время суток», описанный в ISO 8601:2019.

Так как ISO 8601 не включает правильный часовой пояс, заданная строка будет преобразована в UTC, а её смещение во времени в секундах будет возвращено в качестве части этой функции. Поэтому информация о смещении должна быть в строке.

Как указано в стандарте, разделитель «T» может быть опущен по желанию, так как в этой функции нет двусмысленности.

Обратите внимание, что високосные секунды не поддерживаются встроенным Calendar.ISO.

Примеры

iex> {:ok, datetime, 0} = DateTime.from_iso8601("2015-01-23T23:50:07Z")
iex> datetime
~U[2015-01-23 23:50:07Z]

iex> {:ok, datetime, 9000} = DateTime.from_iso8601("2015-01-23T23:50:07.123+02:30")
iex> datetime
~U[2015-01-23 21:20:07.123Z]

iex> {:ok, datetime, 9000} = DateTime.from_iso8601("2015-01-23T23:50:07,123+02:30")
iex> datetime
~U[2015-01-23 21:20:07.123Z]

iex> {:ok, datetime, 0} = DateTime.from_iso8601("-2015-01-23T23:50:07Z")
iex> datetime
~U[-2015-01-23 23:50:07Z]

iex> {:ok, datetime, 9000} = DateTime.from_iso8601("-2015-01-23T23:50:07,123+02:30")
iex> datetime
~U[-2015-01-23 21:20:07.123Z]

iex> {:ok, datetime, 9000} = DateTime.from_iso8601("20150123T235007.123+0230", :basic)
iex> datetime
~U[2015-01-23 21:20:07.123Z]

iex> DateTime.from_iso8601("2015-01-23P23:50:07")
{:error, :invalid_format}
iex> DateTime.from_iso8601("2015-01-23T23:50:07")
{:error, :missing_offset}
iex> DateTime.from_iso8601("2015-01-23 23:50:61")
{:error, :invalid_time}
iex> DateTime.from_iso8601("2015-01-32 23:50:07")
{:error, :invalid_date}
iex> DateTime.from_iso8601("2015-01-23T23:50:07.123-00:00")
{:error, :invalid_format}

from_iso8601(string, calendar, format)Source

@spec from_iso8601(String.t(), Calendar.calendar(), :extended | :basic) ::
  {:ok, t(), Calendar.utc_offset()} | {:error, atom()}

Преобразует в ISO8601, указав как календарь, так и режим.

См. from_iso8601/2 для получения дополнительной информации.

Примеры

iex> {:ok, datetime, 9000} = DateTime.from_iso8601("2015-01-23T23:50:07,123+02:30", Calendar.ISO, :extended)
iex> datetime
~U[2015-01-23 21:20:07.123Z]

iex> {:ok, datetime, 9000} = DateTime.from_iso8601("20150123T235007.123+0230", Calendar.ISO, :basic)
iex> datetime
~U[2015-01-23 21:20:07.123Z]

from_naive(naive_datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec from_naive(
  Calendar.naive_datetime(),
  Calendar.time_zone(),
  Calendar.time_zone_database()
) ::
  {:ok, t()}
  | {:ambiguous, first_datetime :: t(), second_datetime :: t()}
  | {:gap, t(), t()}
  | {:error,
     :incompatible_calendars
     | :time_zone_not_found
     | :utc_only_time_zone_database}

Преобразует данное NaiveDateTime в DateTime.

Ожидает часовой пояс для размещения NaiveDateTime. Если часовой пояс «Etc/UTC», всегда успешно. В противном случае NaiveDateTime проверяется с помощью базы данных часовых поясов, заданной как time_zone_database. См. раздел «База данных часовых поясов» в документации модуля.

Примеры

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

Когда дата и время неоднозначны — например, во время перехода с летнего на зимнее время — возвращаются две возможные действительные даты и время в кортеже. Первая дата и время также является той, которая приходит первой в хронологическом порядке, а вторая — последней.

iex> {:ambiguous, first_dt, second_dt} = DateTime.from_naive(~N[2018-10-28 02:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> first_dt
#DateTime<2018-10-28 02:30:00+02:00 CEST Europe/Copenhagen>
iex> second_dt
#DateTime<2018-10-28 02:30:00+01:00 CET Europe/Copenhagen>

Когда в часовом поясе есть разрыв во времени по часам — например, весной, когда часы переводятся вперёд — возвращаются самая поздняя действительная дата и время непосредственно перед разрывом и самая ранняя действительная дата и время непосредственно после разрыва.

iex> {:gap, just_before, just_after} = DateTime.from_naive(~N[2019-03-31 02:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> just_before
#DateTime<2019-03-31 01:59:59.999999+01:00 CET Europe/Copenhagen>
iex> just_after
#DateTime<2019-03-31 03:00:00+02:00 CEST Europe/Copenhagen>

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

iex> {:ok, datetime} = DateTime.from_naive(~N[2018-07-28 12:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> datetime
#DateTime<2018-07-28 12:30:00+02:00 CEST Europe/Copenhagen>

Эта функция принимает любой map или struct, содержащий по крайней мере те же поля, что и структура NaiveDateTime. Наиболее распространённый пример — это DateTime. В этом случае информация о часовом поясе этого DateTime полностью игнорируется. Это тот же принцип, что и при передаче DateTime в Date.to_iso8601/2. Date.to_iso8601/2 извлекает только поля, относящиеся к дате (календарь, год, месяц и день) из заданной структуры и игнорирует все остальные.

Таким образом, если у вас есть DateTime в одном часовом поясе, вы можете получить то же время по часам в другом часовом поясе. Например, если у вас есть 2018-08-24 10:00:00 в Копенгагене и вам нужен DateTime для 2018-08-24 10:00:00 в UTC, вы можете сделать:

iex> cph_datetime = DateTime.from_naive!(~N[2018-08-24 10:00:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> {:ok, utc_datetime} = DateTime.from_naive(cph_datetime, "Etc/UTC", FakeTimeZoneDatabase)
iex> utc_datetime
~U[2018-08-24 10:00:00Z]

Если вместо этого вам нужен DateTime для той же точки времени в другом часовом поясе, см. функцию DateTime.shift_zone/3, которая преобразовала бы 2018-08-24 10:00:00 в Копенгагене в 2018-08-24 08:00:00 в UTC.

from_naive!(naive_datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec from_naive!(
  NaiveDateTime.t(),
  Calendar.time_zone(),
  Calendar.time_zone_database()
) :: t()

Преобразует заданный NaiveDateTime в DateTime.

Ожидается часовой пояс для размещения NaiveDateTime. Если часовой пояс — "Etc/UTC", преобразование всегда выполняется успешно. В противном случае NaiveDateTime проверяется по базе данных часовых поясов, заданной как time_zone_database. См. раздел «База данных часовых поясов» в документации модуля.

Примеры

iex> DateTime.from_naive!(~N[2016-05-24 13:26:08.003], "Etc/UTC")
~U[2016-05-24 13:26:08.003Z]

iex> DateTime.from_naive!(~N[2018-05-24 13:26:08.003], "Europe/Copenhagen", FakeTimeZoneDatabase)
#DateTime<2018-05-24 13:26:08.003+02:00 CEST Europe/Copenhagen>

from_unix(integer, unit \\ :second, calendar \\ Calendar.ISO)Source

@spec from_unix(integer(), :native | System.time_unit(), Calendar.calendar()) ::
  {:ok, t()} | {:error, atom()}

Преобразует заданное время Unix в DateTime.

Целое число может быть задано в разных единицах измерения в соответствии с System.convert_time_unit/3, и оно будет внутренне преобразовано в микросекунды. Поддерживается до 253402300799 секунд.

Времена Unix всегда находятся в UTC, поэтому DateTime будет возвращено в UTC.

Примеры

iex> {:ok, datetime} = DateTime.from_unix(1_464_096_368)
iex> datetime
~U[2016-05-24 13:26:08Z]

iex> {:ok, datetime} = DateTime.from_unix(1_432_560_368_868_569, :microsecond)
iex> datetime
~U[2015-05-25 13:26:08.868569Z]

iex> {:ok, datetime} = DateTime.from_unix(253_402_300_799)
iex> datetime
~U[9999-12-31 23:59:59Z]

iex> {:error, :invalid_unix_time} = DateTime.from_unix(253_402_300_800)

Единица измерения также может быть целым числом, как в System.time_unit/0:

iex> {:ok, datetime} = DateTime.from_unix(143_256_036_886_856, 1024)
iex> datetime
~U[6403-03-17 07:05:22.320312Z]

Поддерживаются отрицательные значения времени Unix до -377705116800 секунд:

iex> {:ok, datetime} = DateTime.from_unix(-377_705_116_800)
iex> datetime
~U[-9999-01-01 00:00:00Z]

iex> {:error, :invalid_unix_time} = DateTime.from_unix(-377_705_116_801)

from_unix!(integer, unit \\ :second, calendar \\ Calendar.ISO)Source

@spec from_unix!(integer(), :native | System.time_unit(), Calendar.calendar()) :: t()

Преобразует заданное время Unix в DateTime.

Целое число может быть задано в разных единицах измерения в соответствии с System.convert_time_unit/3, и оно будет внутренне преобразовано в микросекунды.

Времена Unix всегда находятся в UTC, поэтому DateTime будет возвращено в UTC.

Примеры

# An easy way to get the Unix epoch is passing 0 to this function
iex> DateTime.from_unix!(0)
~U[1970-01-01 00:00:00Z]

iex> DateTime.from_unix!(1_464_096_368)
~U[2016-05-24 13:26:08Z]

iex> DateTime.from_unix!(1_432_560_368_868_569, :microsecond)
~U[2015-05-25 13:26:08.868569Z]

iex> DateTime.from_unix!(143_256_036_886_856, 1024)
~U[6403-03-17 07:05:22.320312Z]

new(date, time, time_zone \\ "Etc/UTC", time_zone_database \\ Calendar.get_time_zone_database())Source

@spec new(Date.t(), Time.t(), Calendar.time_zone(), Calendar.time_zone_database()) ::
  {:ok, t()}
  | {:ambiguous, first_datetime :: t(), second_datetime :: t()}
  | {:gap, t(), t()}
  | {:error,
     :incompatible_calendars
     | :time_zone_not_found
     | :utc_only_time_zone_database}

Создаёт DateTime из структур даты и времени.

Ожидается часовой пояс для размещения DateTime. Если часовой пояс не передан, он будет по умолчанию "Etc/UTC", что всегда выполняется успешно. В противном случае DateTime проверяется по базе данных часовых поясов, заданной как time_zone_database. См. раздел «База данных часовых поясов» в документации модуля.

Примеры

iex> DateTime.new(~D[2016-05-24], ~T[13:26:08.003], "Etc/UTC")
{:ok, ~U[2016-05-24 13:26:08.003Z]}

Если DateTime неоднозначна — например, при переходе с летнего на зимнее время — возвращаются две возможные допустимые DateTime в кортеже. Первая DateTime также является той, которая появляется первой хронологически, а вторая — последней.

iex> {:ambiguous, first_dt, second_dt} = DateTime.new(~D[2018-10-28], ~T[02:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> first_dt
#DateTime<2018-10-28 02:30:00+02:00 CEST Europe/Copenhagen>
iex> second_dt
#DateTime<2018-10-28 02:30:00+01:00 CET Europe/Copenhagen>

Если в момент времени есть разрыв — например, весной, когда стрелки переводят вперёд — возвращаются последнее допустимое значение DateTime непосредственно перед разрывом и первое допустимое значение DateTime непосредственно после разрыва.

iex> {:gap, just_before, just_after} = DateTime.new(~D[2019-03-31], ~T[02:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> just_before
#DateTime<2019-03-31 01:59:59.999999+01:00 CET Europe/Copenhagen>
iex> just_after
#DateTime<2019-03-31 03:00:00+02:00 CEST Europe/Copenhagen>

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

iex> {:ok, datetime} = DateTime.new(~D[2018-07-28], ~T[12:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> datetime
#DateTime<2018-07-28 12:30:00+02:00 CEST Europe/Copenhagen>

new!(date, time, time_zone \\ "Etc/UTC", time_zone_database \\ Calendar.get_time_zone_database())Source

@spec new!(Date.t(), Time.t(), Calendar.time_zone(), Calendar.time_zone_database()) ::
  t()

Создаёт DateTime из структур даты и времени, поднимая исключение при ошибках.

Ожидается часовой пояс для размещения DateTime. Если часовой пояс не передан, он будет по умолчанию "Etc/UTC", что всегда выполняется успешно. В противном случае DateTime проверяется по базе данных часовых поясов, заданной как time_zone_database. См. раздел «База данных часовых поясов» в документации модуля.

Примеры

iex> DateTime.new!(~D[2016-05-24], ~T[13:26:08.003], "Etc/UTC")
~U[2016-05-24 13:26:08.003Z]

Если DateTime неоднозначна — например, при переходе с летнего на зимнее время — будет поднято исключение.

iex> DateTime.new!(~D[2018-10-28], ~T[02:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
** (ArgumentError) cannot build datetime with ~D[2018-10-28] and ~T[02:30:00] because such instant is ambiguous in time zone Europe/Copenhagen as there is an overlap between #DateTime<2018-10-28 02:30:00+02:00 CEST Europe/Copenhagen> and #DateTime<2018-10-28 02:30:00+01:00 CET Europe/Copenhagen>

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

iex> DateTime.new!(~D[2019-03-31], ~T[02:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
** (ArgumentError) cannot build datetime with ~D[2019-03-31] and ~T[02:30:00] because such instant does not exist in time zone Europe/Copenhagen as there is a gap between #DateTime<2019-03-31 01:59:59.999999+01:00 CET Europe/Copenhagen> and #DateTime<2019-03-31 03:00:00+02:00 CEST Europe/Copenhagen>

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

iex> datetime = DateTime.new!(~D[2018-07-28], ~T[12:30:00], "Europe/Copenhagen", FakeTimeZoneDatabase)
iex> datetime
#DateTime<2018-07-28 12:30:00+02:00 CEST Europe/Copenhagen>

now(time_zone, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec now(Calendar.time_zone(), Calendar.time_zone_database()) ::
  {:ok, t()} | {:error, :time_zone_not_found | :utc_only_time_zone_database}

Возвращает текущую DateTime в заданном часовом поясе.

По умолчанию используется часовой пояс, возвращаемый Calendar.get_time_zone_database/0, который по умолчанию равен Calendar.UTCOnlyTimeZoneDatabase, который обрабатывает только DateTime "Etc/UTC". Другие базы данных часовых поясов могут быть переданы в качестве аргумента или установлены глобально. См. раздел «База данных часовых поясов» в документации модуля.

Примеры

iex> {:ok, datetime} = DateTime.now("Etc/UTC")
iex> datetime.time_zone
"Etc/UTC"

iex> DateTime.now("Europe/Copenhagen")
{:error, :utc_only_time_zone_database}

iex> DateTime.now("bad timezone", FakeTimeZoneDatabase)
{:error, :time_zone_not_found}

now!(time_zone, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec now!(Calendar.time_zone(), Calendar.time_zone_database()) :: t()

Возвращает текущую DateTime в заданном часовом поясе или поднимает исключение при ошибках.

См. now/2 для получения дополнительной информации.

Примеры

iex> datetime = DateTime.now!("Etc/UTC")
iex> datetime.time_zone
"Etc/UTC"

iex> DateTime.now!("Europe/Copenhagen")
** (ArgumentError) cannot get current datetime in "Europe/Copenhagen" time zone, reason: :utc_only_time_zone_database

iex> DateTime.now!("bad timezone", FakeTimeZoneDatabase)
** (ArgumentError) cannot get current datetime in "bad timezone" time zone, reason: :time_zone_not_found

shift_zone(datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec shift_zone(t(), Calendar.time_zone(), Calendar.time_zone_database()) ::
  {:ok, t()} | {:error, :time_zone_not_found | :utc_only_time_zone_database}

Изменяет часовой пояс DateTime.

Возвращает DateTime для той же точки во времени, но в указанном часовом поясе. Предполагается, что DateTime допустима и существует в заданном часовом поясе и календаре.

По умолчанию используется база данных часовых поясов, возвращаемая Calendar.get_time_zone_database/0, которая по умолчанию равна Calendar.UTCOnlyTimeZoneDatabase, обрабатывающая только "Etc/UTC" DateTime. Другие базы данных часовых поясов могут быть переданы в качестве аргумента или установлены глобально. См. раздел «База данных часовых поясов» в документации модуля.

Примеры

iex> {:ok, pacific_datetime} = DateTime.shift_zone(~U[2018-07-16 10:00:00Z], "America/Los_Angeles", FakeTimeZoneDatabase)
iex> pacific_datetime
#DateTime<2018-07-16 03:00:00-07:00 PDT America/Los_Angeles>

iex> DateTime.shift_zone(~U[2018-07-16 10:00:00Z], "bad timezone", FakeTimeZoneDatabase)
{:error, :time_zone_not_found}

shift_zone!(datetime, time_zone, time_zone_database \\ Calendar.get_time_zone_database())Source

@spec shift_zone!(t(), Calendar.time_zone(), Calendar.time_zone_database()) :: t()

Изменяет часовой пояс DateTime или поднимает исключение при ошибках.

См. shift_zone/3 для получения дополнительной информации.

Примеры

iex> DateTime.shift_zone!(~U[2018-07-16 10:00:00Z], "America/Los_Angeles", FakeTimeZoneDatabase)
#DateTime<2018-07-16 03:00:00-07:00 PDT America/Los_Angeles>

iex> DateTime.shift_zone!(~U[2018-07-16 10:00:00Z], "bad timezone", FakeTimeZoneDatabase)
** (ArgumentError) cannot shift ~U[2018-07-16 10:00:00Z] to "bad timezone" time zone, reason: :time_zone_not_found

to_date(datetime)Source

@spec to_date(Calendar.datetime()) :: Date.t()

Преобразует DateTime в Date.

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

Примеры

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.to_date(dt)
~D[2000-02-29]

to_gregorian_seconds(datetime)Source

@spec to_gregorian_seconds(Calendar.datetime()) :: {integer(), non_neg_integer()}

Преобразует структуру DateTime в количество грегорианских секунд и микросекунд.

Примеры

iex> dt = %DateTime{year: 0000, month: 1, day: 1, zone_abbr: "UTC",
...>                hour: 0, minute: 0, second: 1, microsecond: {0, 0},
...>                utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
iex> DateTime.to_gregorian_seconds(dt)
{1, 0}

iex> dt = %DateTime{year: 2020, month: 5, day: 1, zone_abbr: "UTC",
...>                hour: 0, minute: 26, second: 31, microsecond: {5000, 0},
...>                utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
iex> DateTime.to_gregorian_seconds(dt)
{63_755_511_991, 5000}

iex> dt = %DateTime{year: 2020, month: 5, day: 1, zone_abbr: "CET",
...>                hour: 1, minute: 26, second: 31, microsecond: {5000, 0},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.to_gregorian_seconds(dt)
{63_755_511_991, 5000}

to_iso8601(datetime, format \\ :extended, offset \\ nil)Source

@spec to_iso8601(Calendar.datetime(), :basic | :extended, nil | integer()) ::
  String.t()

Преобразует заданную DateTime в формат ISO 8601:2019.

По умолчанию DateTime.to_iso8601/2 возвращает DateTime в формате «расширенный» для удобства чтения человеком. Он также поддерживает формат «основной» через передачу :basic параметра.

Поддерживает преобразование только DateTime в календаре ISO, попытка преобразования DateTime из других календарей приведёт к исключению. Вы также можете дополнительно указать смещение для отформатированной строки.

ПРЕДУПРЕЖДЕНИЕ: формат DateTime ISO 8601 не содержит часовой пояс ни его аббревиатуры, что означает потерю информации при преобразовании в такой формат.

Примеры

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.to_iso8601(dt)
"2000-02-29T23:00:07+01:00"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "UTC",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
iex> DateTime.to_iso8601(dt)
"2000-02-29T23:00:07Z"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.to_iso8601(dt, :extended)
"2000-02-29T23:00:07-04:00"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.to_iso8601(dt, :basic)
"20000229T230007-0400"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.to_iso8601(dt, :extended, 3600)
"2000-03-01T04:00:07+01:00"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.to_iso8601(dt, :extended, 0)
"2000-03-01T03:00:07+00:00"

iex> dt = %DateTime{year: 2000, month: 3, day: 01, zone_abbr: "UTC",
...>                hour: 03, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
iex> DateTime.to_iso8601(dt, :extended, 0)
"2000-03-01T03:00:07Z"

iex> {:ok, dt, offset} = DateTime.from_iso8601("2000-03-01T03:00:07Z")
iex> "2000-03-01T03:00:07Z" = DateTime.to_iso8601(dt, :extended, offset)
END_OF_DOCUMENT_MARKER

to_naive(datetime)Source

@spec to_naive(Calendar.datetime()) :: NaiveDateTime.t()

Преобразует заданный datetime в NaiveDateTime.

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

Примеры

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 1},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.to_naive(dt)
~N[2000-02-29 23:00:07.0]

to_string(datetime)Source

@spec to_string(Calendar.datetime()) :: String.t()

Преобразует заданный datetime в строку в соответствии с его календарём.

Примеры

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.to_string(dt)
"2000-02-29 23:00:07+01:00 CET Europe/Warsaw"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "UTC",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: 0, std_offset: 0, time_zone: "Etc/UTC"}
iex> DateTime.to_string(dt)
"2000-02-29 23:00:07Z"

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "AMT",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 0},
...>                utc_offset: -14400, std_offset: 0, time_zone: "America/Manaus"}
iex> DateTime.to_string(dt)
"2000-02-29 23:00:07-04:00 AMT America/Manaus"

iex> dt = %DateTime{year: -100, month: 12, day: 19, zone_abbr: "CET",
...>                hour: 3, minute: 20, second: 31, microsecond: {0, 0},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Stockholm"}
iex> DateTime.to_string(dt)
"-0100-12-19 03:20:31+01:00 CET Europe/Stockholm"

to_time(datetime)Source

@spec to_time(Calendar.datetime()) :: Time.t()

Преобразует DateTime в Time.

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

Примеры

iex> dt = %DateTime{year: 2000, month: 2, day: 29, zone_abbr: "CET",
...>                hour: 23, minute: 0, second: 7, microsecond: {0, 1},
...>                utc_offset: 3600, std_offset: 0, time_zone: "Europe/Warsaw"}
iex> DateTime.to_time(dt)
~T[23:00:07.0]

to_unix(datetime, unit \\ :second)Source

@spec to_unix(Calendar.datetime(), System.time_unit()) :: integer()

Преобразует заданный datetime в Unix-время.

Ожидается, что datetime использует календарь ISO с годом, большим или равным 0.

Будет возвращено целое число с заданным значением unit, согласно System.convert_time_unit/3.

Примеры

iex> 1_464_096_368 |> DateTime.from_unix!() |> DateTime.to_unix()
1464096368

iex> dt = %DateTime{calendar: Calendar.ISO, day: 20, hour: 18, microsecond: {273806, 6},
...>                minute: 58, month: 11, second: 19, time_zone: "America/Montevideo",
...>                utc_offset: -10800, std_offset: 3600, year: 2014, zone_abbr: "UYST"}
iex> DateTime.to_unix(dt)
1416517099

iex> flamel = %DateTime{calendar: Calendar.ISO, day: 22, hour: 8, microsecond: {527771, 6},
...>                minute: 2, month: 3, second: 25, std_offset: 0, time_zone: "Etc/UTC",
...>                utc_offset: 0, year: 1418, zone_abbr: "UTC"}
iex> DateTime.to_unix(flamel)
-17412508655

truncate(datetime, precision)Source

@spec truncate(Calendar.datetime(), :microsecond | :millisecond | :second) :: t()

Возвращает заданное значение datetime с полем микросекунд, усечённым до заданной точности (:microsecond, :millisecond или :second).

Заданное datetime возвращается без изменений, если оно уже имеет меньшую точность, чем заданная.

Примеры

iex> dt1 = %DateTime{year: 2017, month: 11, day: 7, zone_abbr: "CET",
...>                 hour: 11, minute: 45, second: 18, microsecond: {123456, 6},
...>                 utc_offset: 3600, std_offset: 0, time_zone: "Europe/Paris"}
iex> DateTime.truncate(dt1, :microsecond)
#DateTime<2017-11-07 11:45:18.123456+01:00 CET Europe/Paris>

iex> dt2 = %DateTime{year: 2017, month: 11, day: 7, zone_abbr: "CET",
...>                 hour: 11, minute: 45, second: 18, microsecond: {123456, 6},
...>                 utc_offset: 3600, std_offset: 0, time_zone: "Europe/Paris"}
iex> DateTime.truncate(dt2, :millisecond)
#DateTime<2017-11-07 11:45:18.123+01:00 CET Europe/Paris>

iex> dt3 = %DateTime{year: 2017, month: 11, day: 7, zone_abbr: "CET",
...>                 hour: 11, minute: 45, second: 18, microsecond: {123456, 6},
...>                 utc_offset: 3600, std_offset: 0, time_zone: "Europe/Paris"}
iex> DateTime.truncate(dt3, :second)
#DateTime<2017-11-07 11:45:18+01:00 CET Europe/Paris>

utc_now(calendar \\ Calendar.ISO)Source

@spec utc_now(Calendar.calendar()) :: t()

Возвращает текущее значение datetime в UTC.

Если вам нужно текущее время в Unix-секундах, используйте System.os_time/1 вместо этого.

Примеры

iex> datetime = DateTime.utc_now()
iex> datetime.time_zone
"Etc/UTC"

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.14.1/DateTime.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API