Это проблема, с которой я столкнулся несколько раз. Представьте, что у вас есть запись, которую вы хотите сохранить в таблице базы данных. Эта таблица имеет столбец DateTime с именем «date_created». Эта конкретная запись была создана очень давно, и вы не совсем уверены в точной дате, но знаете год и месяц. Другие записи вы знаете только год. Другие записи вы знаете день, месяц и год.
Вы не можете использовать поле DateTime, потому что «май 1978» не является допустимой датой. Если вы разделите его на несколько столбцов, вы потеряете возможность запроса. Кто-нибудь еще сталкивался с этим, если так, как вы справились с этим?
Чтобы прояснить систему, которую я строю, это система, которая отслеживает архивы. Некоторый контент был создан давно, и все, что мы знаем, это «май 1978». Я мог бы хранить его как 1 мая 1978 года, но только с некоторым способом обозначить, что эта дата точна только для месяца. Таким образом, спустя несколько лет, когда я получаю этот архив, меня не смущает, когда даты не совпадают.
Для моих целей важно различать «неизвестный день в мае 1978 года» с «1 мая 1978 года». Кроме того, я не хотел бы хранить неизвестные как 0, как «0 мая 1978 года», потому что большинство систем баз данных отклонят это как недопустимое значение даты.
источник
Ответы:
Сохраните все даты в обычном поле ДАТА в базе данных и получите дополнительное поле точности, насколько точным является поле ДАТА.
date_created_accuracy: 1 = точная дата, 2 = месяц, 3 = год.
Если ваша дата нечеткая (например, май 1980 г.), сохраните ее в начале периода (например, 1 мая 1980 г.). Или, если ваша дата соответствует году (например, 1980), сохраните ее как 1 января. 1980 с соответствующим значением точности.
Этот способ может легко запросить несколько естественным образом и по-прежнему иметь представление о точных датах. Например, это позволяет запрашивать даты между
Jan 1st 1980
иFeb 28th 1981
и получать нечеткие даты1980
иMay 1980
.источник
select * from mytable where date_created between "1980/1/1" and "1981/2/28" and date_created_accuracy <= 2;
, Genius.date_created_accuracy
поля. Вы можете отобразить «May 1980» или просто «1980» в результатах или пользовательском интерфейсе, если это так точно, как указано в поле.Если вам не нужно использовать этот тип данных в качестве обычной информации о дате и времени, подойдет любой простой формат строки.
Но если вам нужно сохранить все функциональные возможности, я могу придумать два обходных пути, оба из которых требуют дополнительной информации, хранящейся в базе данных:
min date
иmax date
поля, которые имеют разные значения для «неполных» данных, но будут совпадать для точных дат.type
поле в записи и сохранить, какая информация отсутствует.источник
min date
иmax date
поля. Я думаю, что это самое гибкое, но точное и простое в использовании решение.Это на самом деле скорее определение требований, чем техническая проблема - вам нужно сосредоточиться на том, «как мы можем определить даты в прошлом», и техническое решение будет реализовано.
Времена, когда мне приходилось приближаться к чему-то подобному, обычно:
Иногда нужно что-то сделать, например, сделать даты нечеткими - например, одна дата может понадобиться для ответа на запрос чего-либо в мае 1978 года. Это выполнимо - просто сделайте ваши поля create_date 2, старые записи получают 30 дни распределяются по мере необходимости, новые получают 2 одинаковых значения.
источник
Самый простой способ указать, является ли дата точной, состоит в том, чтобы создать поле точности INT (1) со значением по умолчанию NULL.
Если дата является точной, сохраните дату и время в «date_created» и оставьте точность NULL
Если дата является точной только для месяца, храните дату-время как 1-е число месяца со значением точности 1
Если дата является точной только для года, дата-время магазина 1 января со значением точности 2
Вы можете использовать разные числа для хранения разных значений, таких как первый квартал и т. Д.
источник
В прошлом я хранил точные даты как дату начала и дату окончания. День 21, 2102 будет представлен как начало = 12 часов, может 21,2012 и конец = 12 часов, может быть 22,2012. 2012 год будет представлен как начало = 12 часов утра; январь 1,2012; конец = 12 часов утра; январь 1,2013.
Я не уверен, рекомендую ли я такой подход. При отображении информации пользователю необходимо правильно определить, что диапазон дат точно охватывает день, чтобы показать «25 мая» вместо двух сверхконкретных конечных точек (что означает работу с переходом на летнее время и т. Д.).
Однако, когда вы не пытаетесь перевести на человека, программирование с конечными точками намного проще, чем с точностью + центр. Вы не заканчиваете большим количеством случаев. Это довольно мило.
источник
Почему бы не хранить две даты.
Created_After и Created_Before. Фактическая семантика, которая «создается в или после» и «создается в или до»
Так что если вы знаете точную дату, то Created_After и Created_Before будут одной и той же датой.
Если вы знаете, что это была первая неделя мая 2000 года, то Created_After = '2000-05-01' и Created_Before = '2000-05-07'.
Если вы просто знаете май 1999 года, тогда значения будут «1999-05-01» и «1999-05-30».
Если это «лето 42 года», то значения будут «1942-06-01» и «1942-08-31».
Эта схема проста для запроса с помощью обычного SQL и довольно проста для пользователя, не являющегося техническим специалистом.
Например, чтобы найти все документы, которые могли быть созданы в мае 2001 года:
Наоборот, чтобы найти все документы, которые были определенно созданы в мае 2001 года:
источник
Формат даты и времени ISO 8601 поставляется с определением продолжительности, например
2012-01-01P1M
(читай: 2012, 1 января, период: 1 месяц) - это то, что должно быть «в январе 2012».Я бы использовал это для хранения данных. Для этого вам может потребоваться поле базы данных типа String. Это другая тема, как провести разумный поиск по этому вопросу.
источник
Как правило, я все еще сохраняю их, так как даты общего бизнеса запросов все еще возможны, даже если они немного менее точны.
Если важно знать точность, которую я имел в прошлом, то либо сохранял «окно» точности либо в виде +/- десятичной дроби, либо в виде поиска (день, месяц, год и т. Д.). В других случаях вместо окна я просто сохраняю исходное значение даты в виде строки и преобразую все, что я могу, в datetime, возможно, 1978-05-01 00:00:00 и «май 1978» для вашего данного примера.
источник
Говорит кто? Вот что вы делаете:
Поэтому, если я сделаю вставку вроде:
insert into thistable (Day, Month, Year) values (-1, 2, 2012);
тогда TheDate станет 1 февраля 2013 года, но я буду знать, что это действительно неопределенная дата 2 марта 2012 года из-за -1 в поле Day.Если я
insert into thistable (TheDate) values ('2/5/2012');
тогда Днем будет 5, Месяцем будет 2, а Годом будет 2012, и поскольку ни один из них не равен -1, я буду знать, что это точная дата.Я не теряю возможность запроса, потому что триггер вставки / обновления гарантирует, что мои 3 поля (День, Месяц, Год) всегда производят значение DateTime в TheDate, к которому можно обращаться.
источник
Другой вариант - хранить даты как целые числа в форме
YYYYMMDD
.19510000
19510300
19510314
0
Выгоды
Вы можете хранить нечеткую дату в одном поле вместо двух полей даты или даты и точности, как предполагают многие другие ответы.
Запросы все еще просты:
SELECT * FROM table WHERE thedate>=19510000 and thedate<19520000
SELECT * FROM table where thedate>=19510300 and thedate<19510400
SELECT * FROM table where thedate=19510314
ПРИМЕЧАНИЯ
GetDateString(int fuzzyDate)
довольно простым для реализации.99
вместо «padding»00
месяц или день.источник
ISO 8601 также определяет синтаксис для «нечетких дат». 12 февраля 2012 года в 3 часа дня будет «2012-02-12T15», а февраля 2012 года может быть просто «2012-02». Это расширяется, используя стандартную лексикографическую сортировку:
источник
Вот мой взгляд на это:
Переход от нечеткой даты к объекту даты и времени (который будет помещаться в базу данных)
И затем функция, которая берет объект datetime и перемещает его обратно в нечеткую дату.
А потом юнит тест. Я пропустил какие-либо дела?
Существует угловой случай, когда событие, которое точно произошло,
2001-01-01T00:00:00.333333
но система будет интерпретироваться как «только 2001 год», но это кажется маловероятным.источник
Я работаю в издательской компании, которая занимается множеством старых книг, где мы часто не можем получить точные даты вещей. У нас обычно есть два поля для данной записи даты, дата и около логического:
Мы используем поле даты, чтобы указать дату какого-либо события или дату, которая является «достаточно близкой» в случае, когда мы не знаем истинную дату. В случае, если мы не знаем истинную дату, мы помечаем
dateCirca
поле какY
и назначаем достаточно близкую дату, которая помечена как «1-я», напримеристочник
обзор
Существует много возможных представлений и, следовательно, схем баз данных для хранения нечетких дат (или даже просто нечетких дат):
[1], [2] и [3] - все (неявно) однородные интервалы, то есть набор (одинаково) возможных моментов времени.
[4] является наиболее выразительным, т. Е. Когда допускаются любые возможные (или, по крайней мере, произвольно длинные) письменные предложения или фразы на языке. Но с этим труднее всего работать. В пределе ИИ на уровне человека должен был бы обрабатывать произвольные значения. Практически, диапазон возможных значений должен быть строго ограничен, и альтернативные «структурированные» значения, вероятно, предпочтительнее для многих операций, например, сортировки, поиска.
[5], вероятно, является наиболее общим компактным представлением, которое (несколько) практично.
Единые интервалы
Унифицированные интервалы - это самый простой и компактный способ представления набора (возможных) значений даты и времени.
Для [1] части значения даты и времени игнорируются, то есть части, соответствующие единицам, более точным, чем указанная точность или точность; в противном случае это эквивалентно [2], а код точности / точности эквивалентен интервалу с теми же единицами (и подразумеваемой величиной 1).
[2] и [3] выразительно эквивалентны. [1] строго менее выразителен, чем любой, поскольку существуют эффективные интервалы, которые не могут быть представлены [1], напр. нечеткая дата-время, эквивалентная 12-часовому интервалу, который охватывает границу даты.
[1] проще для пользователей, чем любое другое представление, и, как правило, требует (хотя бы немного) меньшего ввода текста. Если даты и время можно вводить в различных текстовых представлениях, например, «2013», «2014-3», «2015-5-2», «30.07.2016, 11p», «2016-07-31 18:15» Точность или точность также может быть выведена автоматически из входных данных.
Точность или точность [1] также проще всего преобразовать в форму, которая будет передаваться пользователям, например, «2015-5 с точностью до месяца» в «май 2015», по сравнению с «13 мая 2015, 2р, плюс или минус 13,5 дней» (обратите внимание, что последний в любом случае не может быть представлен [1]).
Струны
Практически, строковые значения необходимо преобразовывать в другие представления для запроса, сортировки или иного сравнения нескольких значений. Таким образом, хотя любой письменный естественный (человеческий) язык строго более выразителен, чем [1], [2], [3] или [5], у нас пока нет средств для обработки чего-то большего, чем стандартные текстовые представления или форматы. Учитывая это, это, вероятно, наименее полезное представление само по себе .
Одним из преимуществ этого представления является то, что на практике значения должны быть презентабельными для пользователей как есть и не требовать преобразования, чтобы их было легко понять.
Распределение вероятностей
Распределения вероятностей обобщают представления равномерных интервалов [1], [2], [3] и (возможно) эквивалентны (общему) строковому представлению [4].
Одним из преимуществ распределения вероятностей над строками является то, что первое является однозначным.
[5-1] будет подходить для значений, которые (в основном) соответствуют существующему распределению, например, значение даты-времени, выводимое из устройства, для которого известно (или считается), что измерения соответствуют определенному распределению.
[5-2], вероятно, является лучшим (несколько) практичным способом компактного представления произвольных значений «нечеткой даты-времени». Конечно, вычислимость конкретных распределений вероятностей имела значение, и существуют определенные интересные (и, возможно, невозможные) проблемы, которые необходимо решить при запросе, сортировке или сравнении различных значений, но многое из этого, вероятно, уже известно или решено где-то в существующих математическая и статистическая литература, так что это определенно предельно общее и однозначное представление.
источник
Мне очень нравится решение Джеймса Андерсона - точное определение даты - это способ получить наиболее гибкую структуру запроса. Другим способом достижения того же является использование начала, конца или даже центра
date
плюс плюсinterval
(доступно по крайней мере в PostgreSQL , Oracle и SQLAlchemy ).источник
В вашем случае вам нужен только год, месяц и день. Требуется год и месяц, день необязательный. Я бы использовал что-то вроде этого:
Кроме того, вы все еще можете очень эффективно использовать индексы. (Крошечный = минус, очереди становятся немного более «сложными» (более длинными).
источник
1978-??-31
?Я просто сохраню точное время для обычных дат и сделаю часть времени нечеткой даты общей, например, 00:00:00. Затем я бы сделал все нечеткие даты 1-го числа месяца.
Когда вы запрашиваете, вы
Есть лучшие решения, чем это, но я лично ненавижу метаданные (данные о моих данных). У него просто есть привычка выходить из-под контроля через некоторое время.
источник