Nano Hash - криптовалюты, майнинг, программирование

Сохранить день недели и время?

У меня вопрос из двух частей о хранении дней недели и времени в базе данных. Я использую Rails 4.0, Ruby 2.0.0 и Postgres.

У меня есть определенные мероприятия, и у этих событий есть расписание. Например, для мероприятия «Парашютизм» у меня могут быть вторник, среда и 15:00.

  1. Есть ли у меня способ сохранить запись за вторник и среду в одну строку или у меня должно быть две записи?
  2. Как лучше всего хранить день и время? Есть ли способ сохранить день недели и время (не дату и время) или это должны быть отдельные столбцы? Если бы они были разделены, как бы мне сохранить день недели? Я думал о том, чтобы сохранить их как целые числа, 0 для воскресенья, 1 для понедельника, поскольку именно так это делает метод wday для класса Time.

Любые предложения были бы очень полезны.


Ответы:


1

Есть ли у меня способ сохранить запись за вторник и среду в одной строке, или у меня должно быть две записи?

Есть несколько способов сохранить несколько временных диапазонов в одной строке. @bma уже предоставила пару из них. Это может быть полезно для экономии места на диске с помощью очень простых временных шаблонов. Чистый, гибкий и нормализованный подход - хранить одну строку на временной диапазон.

Как лучше всего хранить день и время?

Используйте timestamp (или timestamptz, если может быть задействовано несколько часовых поясов). Выберите произвольную промежуточную неделю и просто игнорируйте часть даты, используя аспект дня и времени timestamp. Самый простой и быстрый по моему опыту, и все проверки работоспособности, связанные с датой и временем, встроены автоматически. Я использую диапазон, начинающийся с 1996-01-01 00:00, для нескольких похожих приложений по двум причинам:

  • Первые 7 дней недели совпадают с днем ​​месяца (для sun = 7).
  • В то же время это самый последний високосный год (29 февраля для годовых моделей).

Тип диапазона

Поскольку вы на самом деле имеете дело с временными диапазонами (а не только с днем ​​и временем), я предлагаю использовать встроенный тип диапазона tsrange (или tstzrange). Основное преимущество: вы можете использовать арсенал встроенных функций диапазона и операторы. Требуется Postgres 9.2 или новее.

Например, вы можете создать ограничение исключения, основанное на этом (реализованное внутренне посредством полнофункционального индекса GiST, который может обеспечить дополнительные преимущества), чтобы исключить перекрывающиеся временные диапазоны. Для получения подробной информации рассмотрите этот связанный ответ:

Для этого конкретного ограничения исключения (без перекрывающихся диапазонов на событие) вам необходимо включить в ограничение целочисленный столбец event_id, поэтому вам необходимо установить дополнительный модуль btree_gist. Установите один раз для каждой базы данных с помощью:

CREATE EXTENSION btree_gist;  -- once per db

Или у вас может быть одно простое CHECK ограничение для ограничения разрешенного периода времени с использованием диапазона, указанного оператором <@.

Это могло выглядеть так:

CREATE TABLE event (event_id serial PRIMARY KEY, ...);

CREATE TABLE schedule (
   event_id integer NOT NULL REFERENCES event(event_id)
                    ON DELETE CASCADE ON UPDATE CASCADE
 , t_range  tsrange
 , PRIMARY KEY (event_id, t_range)
 , CHECK (t_range <@ '[1996-01-01 00:00, 1996-01-09 00:00)')  -- restrict period
 , EXCLUDE USING gist (event_id WITH =, t_range WITH &&)      -- disallow overlap
);

Для еженедельного расписания используйте первые семь дней, пн-вс или как вам удобно. Месячные или годовые расписания аналогичным образом.

Как извлечь день недели, время и т. Д.?

@CDub предоставил модуль для работы с ним на стороне Ruby. Я не могу это комментировать, но в Postgres все тоже можно делать с безупречной производительностью.

SELECT ts::time AS t_time           -- get the time (practically no cost)
SELECT EXTRACT(DOW FROM ts) AS dow  -- get day of week (very cheap)

Или аналогичным образом для типов диапазонов:

SELECT EXTRACT(DOW FROM lower(t_range)) AS dow_from  -- day of week lower bound
     , EXTRACT(DOW FROM upper(t_range)) AS dow_to    -- same for upper
     , lower(t_range)::time AS time_from             -- start time
     , upper(t_range)::time AS time_to               -- end time
FROM   schedule;

db ‹› fiddle здесь
Старый sqliddle

ISODOW вместо DOW для EXTRACT() возвращает 7 вместо 0 по воскресеньям. Есть длинный список того, что вы можете извлечь.

Этот связанный ответ демонстрирует, как использовать оператор типа диапазона для вычисления общей продолжительности для временных диапазонов (последняя глава):

11.11.2013

2

Ознакомьтесь с жемчужиной ice_cube (ссылка).

Он может создать для вас объект расписания, который вы можете сохранить в своей базе данных. Вам не нужно создавать две отдельные записи. Для второй части вы можете создать расписание на основе любого правила, и вам не нужно беспокоиться о том, как оно будет сохранено в базе данных. Вы можете использовать методы, предоставляемые гемом, для получения любой информации от объекта постоянного расписания.

10.11.2013

3

В зависимости от того, насколько сложны ваши потребности в планировании, вы можете ознакомиться с RFC 5545, < формат данных расписания href = "http://en.wikipedia.org/wiki/ICalendar" rel = "nofollow"> iCalendar для идей о том, как хранить данные.

Если вам нужно довольно просто, это, вероятно, излишнее. Postgresql имеет множество функций для преобразования даты и времени в любой формат, который вы необходимость.

Чтобы упростить хранение относительных дат и времени, вы можете сохранить день недели как целое число, как вы предложили, а время как тип данных TIME. Если у вас может быть несколько действующих дней недели, вы можете использовать ARRAY.

Eg.

  • ARRAY [2,3] :: INTEGER [] = вторник, среда как день недели
  • '15: 00: 00 ':: ВРЕМЯ = 15:00

[РЕДАКТИРОВАТЬ: Добавьте несколько простых примеров]

/* Custom the time and timetz range types */
CREATE TYPE timerange AS RANGE (subtype = time);

--drop table if exists schedule;
create table schedule (
    event_id    integer not null, /* should be an FK to "events" table */
    day_of_week integer[],
    time_of_day time,
    time_range  timerange,
    recurring   text CHECK (recurring IN ('DAILY','WEEKLY','MONTHLY','YEARLY'))
);

insert into schedule (event_id, day_of_week, time_of_day, time_range, recurring)
values
(1, ARRAY[1,2,3,4,5]::INTEGER[], '15:00:00'::TIME, NULL, 'WEEKLY'),
(2, ARRAY[6,0]::INTEGER[], NULL, '(08:00:00,17:00:00]'::timerange, 'WEEKLY');

select * from schedule;

 event_id | day_of_week | time_of_day |     time_range      | recurring 
----------+-------------+-------------+---------------------+-----------
        1 | {1,2,3,4,5} | 15:00:00    |                     | WEEKLY
        2 | {6,0}       |             | (08:00:00,17:00:00] | WEEKLY

Первая запись может быть прочитана как: событие действительно в 15:00 с понедельника по пятницу, с этим расписанием, происходящим каждую неделю.
Вторая запись может быть прочитана как: событие действительно в субботу и воскресенье с 8:00 до 17:00, происходит каждый неделя.

Тип настраиваемого диапазона «timerange» используется для обозначения нижней и верхней границ вашего временного диапазона.
'(' означает «включающий», а завершающий ']' означает «исключительный» или, другими словами, «больший» чем или равно 8 утра и меньше 5 вечера ".

10.11.2013
  • Не думал, что в postgres можно хранить массивы? 11.11.2013
  • А? Конечно. Существует множество типов данных (включая пользовательские), которые вы можете использовать, включая HSTORE (ключ-значение), JSON, ARRAY нескольких типов данных, многомерные массивы и т. Д. Подробнее на postgresql.org/docs/current/static/datatype.html 11.11.2013
  • хорошо, большое спасибо - единственное, что я пытаюсь понять, это как создать миграцию рельсов, которая делает тип данных day_of_week целочисленным массивом с фиксированными значениями 0..6? 11.11.2013
  • исправлены как типы ENUM? postgresql.org/docs/current/static/datatype-enum.html < / а> 11.11.2013
  • да, только значения 0..6 - я вижу, как это сделать в postgres, просто не используя миграцию рельсов 11.11.2013
  • Извините, я не могу помочь с частью Rails. 11.11.2013
  • @bsiddiqui: обратите внимание, что timetz поддерживается, поскольку он упоминается в стандарте SQL, но этот тип не подходит для использования с DST, и его использование официально не рекомендуется. Подробнее здесь. +1 к типу диапазона. 11.11.2013
  • @ErwinBrandstetter Спасибо за разъяснение по timetz, я не знал, что он сломан. 11.11.2013

  • 4

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

    2.0.0p247 :139 > Date.today
     => Sun, 10 Nov 2013 
    2.0.0p247 :140 > Date.today.strftime("%A")
     => "Sunday" 
    

    strftime похоже, что он может сделать все за вас. Вот специальные документы для этого.

    В частности, для того, о чем вы говорите, похоже, вам понадобится Event таблица, которая has_many :schedules, где Schedule будет иметь start_date метку времени ...

    10.11.2013
  • потому что это повторяющиеся события, поэтому они связаны с определенной датой 11.11.2013
  • Да, я обновил свой ответ. У вас было бы много расписаний на мероприятие, верно? 11.11.2013
  • Итак, если я хочу найти события, которые происходят с понедельника по пятницу, могу ли я сделать запрос на start_date, чтобы узнать это? 11.11.2013
  • Вы найдете все Schedule объекты между указанными датами, а затем вернете уникальные Event идентификаторы. 11.11.2013
  • Если у меня есть расписание с start_date 1/1/13 (вторник), и меня просят события с расписанием с 1/6/13 (воскресенье) по 1/9/13 (среда), просто выполните запрос, чтобы увидеть, какие объекты расписания находятся между датами, он не вернет объект 1/1/13, хотя должен, потому что вторник находится между воскресеньем и средой. 11.11.2013
  • Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..