DateTime
Реализация DateTime с часовым поясом.
Данная структура DateTime может быть представлена как моментальный снимок даты и времени в заданном часовом поясе. Для этого она включает как UTC-смещение, так и стандартное смещение, а также поле сокращения часового пояса, используемое исключительно для форматирования. Обратите внимание, что будущие DateTime не гарантированно существуют, так как часовые пояса могут измениться в будущем из-за геополитических причин. Дополнительную информацию см. в разделе «DateTime как моментальные снимки».
Помните, что сравнения в Elixir с использованием ==/2, >/2, </2 и аналогичных функций являются структурными и основаны на полях структуры DateTime. Для корректного сравнения DateTime используйте функцию compare/2.
Разработчикам следует избегать непосредственного создания структуры DateTime и вместо этого использовать функции, предоставляемые этим модулем, а также функции сторонних библиотек для работы с календарем.
База данных часовых поясов
Многие функции в этом модуле требуют базу данных часовых поясов. По умолчанию используется база данных часовых поясов по умолчанию, возвращаемая функцией Calendar.get_time_zone_database/0, которая по умолчанию устанавливается на Calendar.UTCOnlyTimeZoneDatabase, которая обрабатывает только DateTime в "Etc/UTC" и возвращает {:error, :utc_only_time_zone_database} для любого другого часового пояса.
Также можно настроить другие базы данных часовых поясов. Например, два доступных варианта:
Для их использования убедитесь, что они добавлены в качестве зависимости в mix.exs. Затем их можно настроить либо через конфигурацию:
config :elixir, :time_zone_database, Tzdata.TimeZoneDatabase
либо, вызвав функцию Calendar.put_time_zone_database/1:
Calendar.put_time_zone_database(Tzdata.TimeZoneDatabase)
См. правильные имена в документации по установке библиотеки.
DateTime как моментальные снимки
В первом разделе мы описали DateTime как «моментальный снимок даты и времени в заданном часовом поясе». Давайте рассмотрим пример, чтобы лучше понять это.
Представьте, что кто-то из Польши хочет назначить встречу с кем-то из Бразилии в следующем году. Встреча состоится в 2:30 утра по польскому времени. В какое время встреча состоится в Бразилии?
Вы можете обратиться к базе данных часовых поясов на сегодняшний день, за год до этого, используя API в этом модуле, и получите ответ, который действителен прямо сейчас. Однако этот ответ может быть недействительным в будущем. Почему? Потому что как Польша, так и Бразилия могут изменить свои правила часового пояса, что в конечном итоге повлияет на результат. Например, страна может ввести или отменить «летнее время», что является процессом изменения времени на один час вперед или назад один раз в год. При изменении правил точный момент, когда 2:30 утра по польскому времени будет в Бразилии, может измениться.
Другими словами, при работе с будущими DateTime нет гарантии, что полученные результаты всегда будут корректными, пока событие не произойдет. Поэтому, когда вы запрашиваете будущее время, получаемые ответы являются моментальным снимком, отражающим текущее состояние правил часового пояса. Для DateTime в прошлом это не проблема, так как правила часовых поясов не меняются для прошлых событий.
Хуже того, может оказаться, что 2:30 утра по польскому времени вообще не существует или это неоднозначно. Если определённый часовой пояс использует «летнее время», они переводят свои часы вперёд один раз в год. Когда это происходит, целый час не существует. Затем, когда они переводят часы назад, определённый час произойдёт дважды. Поэтому, если вы хотите назначить встречу, когда происходит такое смещение назад, вам нужно чётко указать, о каком именно 2:30 утра идёт речь. Приложениям, чувствительным к дате и времени, необходимо учитывать эти сценарии и правильно сообщать об этом пользователям.
Хорошая новость: Elixir содержит все необходимые инструменты для решения этих проблем. База данных часовых поясов по умолчанию, используемая Elixir, Calendar.UTCOnlyTimeZoneDatabase, работает только с UTC, который не сталкивается с этими проблемами. Как только вы используете правильную базу данных часовых поясов, функции в этом модуле будут запросить базу данных и вернуть соответствующую информацию. Например, посмотрите, как DateTime.new/4 возвращает разные результаты в зависимости от сценариев, описанных в этом разделе.
Краткое описание
Типы
Функции
- 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, calendar \\ Calendar.ISO)
Парсит расширенный формат «Дата и время» описанный в ISO 8601:2019.
- 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_gregorian_seconds(datetime)
Преобразует структуру
DateTimeв количество грегорианских секунд и микросекунд.- to_iso8601(datetime, format \\ :extended, offset \\ nil)
Преобразует заданное datetime в формат ISO 8601:2019.
- to_naive(map)
Преобразует заданный
datetimeвNaiveDateTime.- to_string(datetime)
Преобразует заданный
datetimeв строку в соответствии с его календарём.- to_unix(datetime, unit \\ :second)
Преобразует заданное
datetimeв время Unix.- truncate(datetime, precision)
Возвращает заданное datetime с микросекундным полем, усеченным до заданной точности (
:microsecond,:millisecondили:second).- utc_now(calendar \\ Calendar.ISO)
Возвращает текущее datetime в UTC.
Типы
t()Исходный код
@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()
} Функции
add(datetime, amount_to_add, unit \\ :second, time_zone_database \\ Calendar.get_time_zone_database())Source
@spec add( Calendar.datetime(), integer(), System.time_unit(), Calendar.time_zone_database() ) :: t()
Добавляет указанное количество времени к DateTime.
Принимает amount_to_add в любом unit доступном у System.time_unit/0. Отрицательные значения будут перемещать во времени назад.
Учитывает такие изменения, как летнее/зимнее время. Это означает, что добавление времени может привести к тому, что время отображения "перескочит назад" во время "перехода на зимнее время" осенью. Добавление всего нескольких секунд к дате и времени непосредственно перед "переходом на летнее время" может привести к увеличению времени отображения более чем на час.
Точность долей секунды остаётся неизменной, аналогично NaiveDateTime.add/2.
Примеры
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>
compare(datetime1, datetime2)Source
@spec compare(Calendar.datetime(), Calendar.datetime()) :: :lt | :eq | :gt
Сравнивает две структуры datetime.
Возвращает :gt если первое datetime позже второго, и :lt в противном случае. Если две datetime равны, возвращается :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()) :: 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"} 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"}} diff(datetime1, datetime2, unit \\ :second)Source
@spec diff(Calendar.datetime(), Calendar.datetime(), System.time_unit()) :: integer()
Вычисляет разницу datetime2 между datetime1.
Результат может быть возвращён в любом unit доступном у System.time_unit/0.
Высокоскоростные секунды не учитываются.
Функция возвращает разницу во времени в секундах, измеренных в соответствии с Calendar.ISO.
Примеры
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 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, calendar \\ Calendar.ISO)Source
@spec from_iso8601(String.t(), Calendar.calendar()) ::
{:ok, t(), Calendar.utc_offset()} | {:error, atom()} Парсит расширенный формат "Дата и время суток", описанный в 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> 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_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_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]}
Когда дата и время являются неоднозначными — например, при переходе с летнего на зимнее время — возвращаются две возможные допустимые даты и время в кортеже. Первое datetime также является тем, которое приходит раньше по хронологии, а второе — последним.
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>
Эта функция принимает любую карту или структуру, которая содержит по крайней мере те же поля, что и структура 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_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]
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) 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 из структур date и time, генерируя исключение при ошибках.
Ожидается часовой пояс для установки 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>
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 из структур date и time.
Ожидается часовой пояс для установки 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 также является той, которая встречается первой хронологически, а вторая — последней.
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> 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 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} Возвращает текущую дату и время в заданном часовом поясе.
По умолчанию используется значение по умолчанию time_zone, возвращаемое 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} 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
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, обрабатывающей только DateTime "Etc/UTC". Другие базы данных часовых поясов могут быть переданы в качестве аргумента или установлены глобально. См. раздел «База данных часовых поясов» в документации модуля.
Примеры
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} to_date(map)Source
@spec to_date(Calendar.datetime()) :: Date.t()
Так как 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) to_naive(map)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(map)Source
@spec to_time(Calendar.datetime()) :: Time.t()
Поскольку 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.
Будет возвращено целое число с заданным типом единиц измерения, согласно System.convert_time_unit/3.
Если вам нужно получить текущее время в секундах Unix, не делайте DateTime.utc_now() |> DateTime.to_unix(). Просто вызовите System.os_time(:second) вместо этого.
Примеры
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()
Возвращает заданную дату и время с усеченным микросекундным значением до заданной точности (:microsecond, :millisecond или :second).
Заданная дата и время возвращается без изменений, если она уже имеет меньшую точность, чем заданная точность.
Примеры
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()
Возвращает текущую дату и время в UTC.
Примеры
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.13.4/DateTime.html