[Elixir/Phoenix, Erlang/OTP, Open source] «O tempora, o mores!»

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
05-Сен-2020 12:35

Для протокола: заголовок я позаимствовал у Цицерона, в Oratio in Catilinam Prima in Senatu Habita.

В реальной жизни мы часто имеем дело с временны́ми интервалами. Свиданки с зубным врачом, бронирование гостиничных номеров, даже ежедневный обеденный перерыв: планирование всего этого — задача подгонки временно́го интервала в ряд других временны́х интервалов.
Допустим, нам пора навестить стоматолога. Я знаю, что мне нужен 1 час для ежегодной плановой проверки. Я могу посетить врача во время обеда или после работы. У доктора есть и другие пациенты. На диаграмме ниже мои рабочие часы показаны фиолетовым цветом, докторские — красным, нерабочие — серым, а счастливо найденный слот, когда мы оба свободны, — зеленым.

Беглого взгляда на эту диаграмму достаточно, чтобы определить время назначенной встречи. Завтра, в обеденное время. Легко, да?
К сожалению, ни один из известных мне языков программирования не предоставляет возможности определить это программно. Последние несколько лет я состою в тесных отношениях с эликсиром, поэтому пришлось написать библиотеку, решающую именно эту проблему.
Итак, встречайте Tempus!
Детали реализации
Сущность, вокруг которой построена вся библиотека — Slot. Он представляет временной интервал самым естественным и простым способом: это структура, с полями from и to, оба типа DateTime. Набор слотов хранится в структуре Slots, под капотом реализованной как AVLTree. Этот выбор был сделан для того, чтобы сохранить базовый список слотов согласованным (упорядоченным и не перекрывающимся) с наименьшими затратами при оптимизации доступа по чтению и записи. Обычно список слотов заполняется при инициализации и потом используется для проверки, поиска свободных интервалов, и тому подобного.
Функция Slots.add/2 добавит в список слотов — новый, объединяя слоты по мере необходимости. Это позволяет просто вставлять новые слоты в конструкцию, не беспокоясь о порядке и перекрытии. Также предусмотрена вспомогательная функция Slots.merge/2 для объединения двух наборов слотов. Последнее особенно удобно, когда нужно, например, найти пустой слот в обеих сериях, как в примере с выбором времени посещения дантиста выше.
Можно также проверить любое время на предмет занятости при помощи функций их модуля Slot: покрывает ли слот заданное время (или другой слот), являются ли слоты непересекающимися, или нет и т. д.
Модуль Tempus
Основной модуль экспортирует функции для работы со слотами, как с прерывистой временной шкалой. Можно добавить любой произвольный интервал времени к началу координат, принимая во внимание слоты; проверить, свободен ли этот интервал, или уже занят слотами, получить следующий свободный или следующий занятый слот, инвертировать временную шкалу, и многое другое.
Вот незамысловатый пример из тестов:
slots =
  [
    Tempus.Slot.wrap(~D|2020-08-07|), # whole day
    %Tempus.Slot{
      from: ~U|2020-08-08 01:01:00Z|, # one minute
      to: ~U|2020-08-08 01:02:00Z|
    },
    %Tempus.Slot{
      from: ~U|2020-08-08 01:03:00Z|, # one minute
      to: ~U|2020-08-08 01:04:00Z|
    }
  ]
  |> Enum.into(%Tempus.Slots{})

Если добавить 0 секунд ко времени, уже занятому слотом, вернется первое доступное время после занятого промежутка.
Tempus.add(slots, ~U|2020-08-08 01:01:30Z|, 0, :second)
#⇒ ~U[2020-08-08 01:02:00Z]

Добавив 70 секунд ко времени, на пять секунд предшествующему первому занятому слоту — ~U[2020-08-08 01:00:55Z] — вернется экземпляр DateTime через пять секунд после второго занятого слота (5sec + занято + 60sec + занято + 5sec):
Tempus.add(slots, ~U|2020-08-08 01:00:55Z|, 70, :second)
#⇒ ~U[2020-08-08 01:04:05Z]

И так далее. Разумеется, можно добавлять и отрицательные значения.
Слияние наборов слотов
Slots.merge/2 понимает Stream в качестве второго аргумента. На данный момент библиотека не поддерживает слияние и использование двух потоков слотов, но вливание потока в существующие временные интервалы возможно. Это может быть полезно, когда у нас есть короткий список, скажем, праздников, и мы хотим объединить его с повторяющимися слотами, например с выходными.
Все функции, возвращающие Slots и / или Slot — гарантированно отдают допустимые объекты (нормализованные, упорядоченные и объединенные по мере необходимости).
Что еще?
Текущая реализация покрывает только наши внутренние потребности, поэтому я был бы рад услышать о том, чего не хватает этой библиотеке и что следует в нее добавить.
Удачных временных интервалов!
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_elixir/phoenix, #_erlang/otp, #_open_source, #_timeseries, #_timeline, #_elixir/phoenix, #_erlang/otp, #_open_source
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 13:14
Часовой пояс: UTC + 5