Spec-Zone.ru › Elixir 1.17

Источник Duration

Структура и функции для работы со временными интервалами.

Структура Duration представляет собой набор единиц измерения времени, позволяющий манипулировать и вычислять временные интервалы.

Единицы измерения даты и времени представлены как целые числа, что позволяет использовать как положительные, так и отрицательные значения.

Микросекунды представлены с помощью кортежа {microsecond, precision}. Это обеспечивает совместимость с другими типами календарей, реализующими время, такими как Time, DateTime и NaiveDateTime.

Сдвиги

Наиболее распространённое использование временных интервалов в стандартной библиотеке Elixir — это «сдвиг» типов календаря.

iex> Date.shift(~D[2016-01-03], month: 2)
~D[2016-03-03]

В примере выше, Date.shift/2 автоматически преобразует единицы в структуру Duration, хотя её можно также задать напрямую:

iex> Date.shift(~D[2016-01-03], Duration.new!(month: 2))
~D[2016-03-03]

Важно отметить, что сдвиг — это не арифметическая операция. Например, добавление date + 1 month + 1 month не даёт того же результата, что и date + 2 months. Посмотрим на пример:

iex> ~D[2016-01-31] |> Date.shift(month: 1) |> Date.shift(month: 1)
~D[2016-03-29]

iex> ~D[2016-01-31] |> Date.shift(month: 2)
~D[2016-03-31]

Как видно выше, результаты различаются, что объясняет, почему операции с временными интервалами называются «сдвигом», а не «сложением». Это происходит потому, что, добавив один месяц к 2016-01-31, мы получим 2016-02-29. Затем добавление ещё одного месяца даёт нам 2016-03-29 вместо 2016-03-31.

В частности, при применении временных интервалов к типам Calendar.ISO:

  • большие единицы (такие как годы и месяцы) применяются перед меньшими (такими как недели, часы, дни и т. д.)

  • единицы сворачиваются в месяцы (:year и :month), секунды (:week, :day, :hour, :minute, :second) и микросекунды (:microsecond ) перед применением

  • 1 год эквивалентен 12 месяцам, 1 неделя — 7 дням. Следовательно, 4 недели не эквивалентны 1 месяцу

  • в случае отсутствия дат результаты округляются до ближайшей корректной даты

Поскольку функции shift/2 учитывают календарь, они гарантированно возвращают допустимые даты/времена, учитывая високосные годы и летнее/зимнее время в соответствующих часовых поясах.

Интервалы

Временные интервалы в Elixir можно комбинировать с операциями над потоками для создания интервалов. Например, чтобы получить следующие три среды, начиная с 17 апреля 2024 года:

iex> ~D[2024-04-17] |> Stream.iterate(&Date.shift(&1, week: 1)) |> Enum.take(3)
[~D[2024-04-17], ~D[2024-04-24], ~D[2024-05-01]]

Однако, ещё раз, важно помнить, что сдвиг временного интервала — это не арифметическая операция, поэтому вам может потребоваться использовать функции в этом модуле в зависимости от того, чего вы хотите добиться. Сравните результаты обоих примеров ниже:

# Adding one month after the other
iex> date = ~D[2016-01-31]
iex> duration = Duration.new!(month: 1)
iex> stream = Stream.iterate(date, fn prev_date -> Date.shift(prev_date, duration) end)
iex> Enum.take(stream, 3)
[~D[2016-01-31], ~D[2016-02-29], ~D[2016-03-29]]

# Multiplying durations by an index
iex> date = ~D[2016-01-31]
iex> duration = Duration.new!(month: 1)
iex> stream = Stream.from_index(fn i -> Date.shift(date, Duration.multiply(duration, i)) end)
iex> Enum.take(stream, 3)
[~D[2016-01-31], ~D[2016-02-29], ~D[2016-03-31]]

Во втором примере постоянно указывается последний день месяца, так как он выполняет операции над временным интервалом, а не сдвигает дату после даты.

Обзор

Типы

duration()

Тип duration определяет структуру %Duration{} или список ключевых слов с допустимыми парами единиц измерения временного интервала.

t()

Тип структуры duration.

unit_pair()

Тип unit_pair определяет пару допустимого ключа единицы измерения временного интервала и значения.

Функции

add(d1, d2)

Складывает единицы заданных временных интервалов d1 и d2.

from_iso8601(string)

Парсит строку с форматом ISO 8601 для временного интервала в структуру Duration.

from_iso8601!(string)

Аналогично from_iso8601/1, но вызывает исключение ArgumentError.

multiply(duration, integer)

Умножает единицы duration на заданное целое число integer.

negate(duration)

Изменяет знак единиц duration на противоположный.

new!(duration)

Создаёт новую структуру Duration из заданного unit_pairs.

subtract(d1, d2)

Вычитает единицы заданных временных интервалов d1 и d2.

to_iso8601(duration)

Преобразует заданный временной интервал duration в строку с форматом ISO 8601-2:2019.

Типы

duration()Источник

@type duration() :: t() | [unit_pair()]

Тип duration определяет структуру %Duration{} или список ключевых слов с допустимыми парами единиц измерения временного интервала.

t()Источник

@type t() :: %Duration{
  day: integer(),
  hour: integer(),
  microsecond: {integer(), 0..6},
  minute: integer(),
  month: integer(),
  second: integer(),
  week: integer(),
  year: integer()
}

Тип структуры duration.

unit_pair()Источник

@type unit_pair() ::
  {:year, integer()}
  | {:month, integer()}
  | {:week, integer()}
  | {:day, integer()}
  | {:hour, integer()}
  | {:minute, integer()}
  | {:second, integer()}
  | {:microsecond, {integer(), 0..6}}

Тип unit_pair определяет пару допустимого ключа единицы измерения временного интервала и значения.

Функции

add(d1, d2)Source

@spec add(t(), t()) :: t()

Складывает единицы заданных промежутков времени d1 и d2.

Учитывает максимальную точность в микросекундах из двух.

Примеры

iex> Duration.add(Duration.new!(week: 2, day: 1), Duration.new!(day: 2))
%Duration{week: 2, day: 3}
iex> Duration.add(Duration.new!(microsecond: {400, 3}), Duration.new!(microsecond: {600, 6}))
%Duration{microsecond: {1000, 6}}

from_iso8601(string)Source

@spec from_iso8601(String.t()) :: {:ok, t()} | {:error, atom()}

Парсит строку интервала времени в формате ISO 8601 в структуру Duration.

Строки интервалов времени, а также отдельные единицы, могут быть опережаемы знаком плюс/минус, чтобы:

  • -PT6H3M парсится как %Duration{hour: -6, minute: -3}
  • -PT6H-3M парсится как %Duration{hour: -6, minute: 3}
  • +PT6H3M парсится как %Duration{hour: 6, minute: 3}
  • +PT6H-3M парсится как %Duration{hour: 6, minute: -3}

Обозначения интервалов времени должны быть предоставлены в порядке величины: P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S.

Только секунды могут быть указаны с десятичной дробью, используя запятую или точку: P1DT4,5S.

Примеры

iex> Duration.from_iso8601("P1Y2M3DT4H5M6S")
{:ok, %Duration{year: 1, month: 2, day: 3, hour: 4, minute: 5, second: 6}}
iex> Duration.from_iso8601("P3Y-2MT3H")
{:ok, %Duration{year: 3, month: -2, hour: 3}}
iex> Duration.from_iso8601("-PT10H-30M")
{:ok, %Duration{hour: -10, minute: 30}}
iex> Duration.from_iso8601("PT4.650S")
{:ok, %Duration{second: 4, microsecond: {650000, 3}}}

from_iso8601!(string)Source

@spec from_iso8601!(String.t()) :: t()

То же, что и from_iso8601/1, но вызывает исключение ArgumentError.

Примеры

iex> Duration.from_iso8601!("P1Y2M3DT4H5M6S")
%Duration{year: 1, month: 2, day: 3, hour: 4, minute: 5, second: 6}
iex> Duration.from_iso8601!("P10D")
%Duration{day: 10}

multiply(duration, integer)Source

@spec multiply(t(), integer()) :: t()

Умножает duration единицы на заданное integer.

Примеры

iex> Duration.multiply(Duration.new!(day: 1, minute: 15, second: -10), 3)
%Duration{day: 3, minute: 45, second: -30}
iex> Duration.multiply(Duration.new!(microsecond: {200, 4}), 3)
%Duration{microsecond: {600, 4}}

negate(duration)Source

@spec negate(t()) :: t()

Изменяет знак duration единиц.

Примеры

iex> Duration.negate(Duration.new!(day: 1, minute: 15, second: -10))
%Duration{day: -1, minute: -15, second: 10}
iex> Duration.negate(Duration.new!(microsecond: {500000, 4}))
%Duration{microsecond: {-500000, 4}}

new!(duration)Source

@spec new!(duration()) :: t()

Создает новую структуру Duration из заданного unit_pairs.

Вызывает исключение ArgumentError при использовании недопустимых пар единиц.

Примеры

iex> Duration.new!(year: 1, week: 3, hour: 4, second: 1)
%Duration{year: 1, week: 3, hour: 4, second: 1}
iex> Duration.new!(second: 1, microsecond: {1000, 6})
%Duration{second: 1, microsecond: {1000, 6}}
iex> Duration.new!(month: 2)
%Duration{month: 2}

subtract(d1, d2)Source

@spec subtract(t(), t()) :: t()

Вычитает единицы заданных промежутков времени d1 и d2.

Учитывает максимальную точность в микросекундах из двух.

Примеры

iex> Duration.subtract(Duration.new!(week: 2, day: 1), Duration.new!(day: 2))
%Duration{week: 2, day: -1}
iex> Duration.subtract(Duration.new!(microsecond: {400, 6}), Duration.new!(microsecond: {600, 3}))
%Duration{microsecond: {-200, 6}}

to_iso8601(duration)Source

@spec to_iso8601(t()) :: String.t()

Преобразует заданный duration в строку формата ISO 8601-2:2019.

Обратите внимание, что эта функция реализует расширение ISO 8601:2019. Это расширение позволяет неделям появляться между месяцами и днями: P3M3W3D, делая его полностью совместимым с любой структурой Duration.

Примеры

iex> Duration.to_iso8601(Duration.new!(year: 3))
"P3Y"
iex> Duration.to_iso8601(Duration.new!(day: 40, hour: 12, minute: 42, second: 12))
"P40DT12H42M12S"
iex> Duration.to_iso8601(Duration.new!(second: 30))
"PT30S"

iex> Duration.to_iso8601(Duration.new!([]))
"PT0S"

iex> Duration.to_iso8601(Duration.new!(second: 1, microsecond: {2_200, 3}))
"PT1.002S"
iex> Duration.to_iso8601(Duration.new!(second: 1, microsecond: {-1_200_000, 4}))
"PT-0.2000S"

Скачать версию ePub

Создано с помощью ExDoc (v0.34.1) для языка программирования Elixir

© 2012-2024 The Elixir Team
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.17.2/Duration.html

Spec-Zone.ru

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