Существует ли стандартный способ представить неопределенные даты в C#?

Я играю вокруг с некоторыми историческими данными, где некоторые даты, которые я знаю точно (т.е. dd/mm/yyyy), пока другие просто yyyy и другие, являются yyyy? (т.е. год сомнителен). Я даже столкнулся с fl, который, по-видимому, означает, "процветал".

В данный момент я использую класс DateTime, который, кажется, не поддерживает установку флага/представление такой неуверенности. Существует ли стандартный способ решить эту проблему?

20
задан Ian Hopkinson 6 March 2010 в 19:32
поделиться

8 ответов

Существуют различные академические работы о способах представления приблизительного времени, например, http://www.musiccog.ohio-state.edu/Humdrum/representations/date.rep.html

Если вы хотите обработать весь объем исторических документов и приблизительные знания, которые вы будете иметь для любого из них, это не простая операция bool / nullable со значениями DateTime.

Я еще не видел библиотеки C# для работы с этим. Мой собственный движок Natural Language Engine для C# может понимать все виды фраз о дате и времени, но он был разработан для другой задачи - он может принять неточный вопрос и запросить базу данных точных значений.

У него есть классы для конкретной даты, диапазона дат, известного года (но без месяца/дня), известного года+месяца (но без даты), полубесконечного диапазона (например, до или после данной даты), ... и, используя их, он может строить запросы к базам данных или перечислять все возможные диапазоны дат, которые могут подразумеваться. Например, вы можете спросить его "кто звонил в прошлом году в пятницу после 16:00", и он может сгенерировать соответствующий SQL-запрос.

Если вы хотите сделать это правильно, то это не так просто! На вашем месте я бы захватил строковое значение с оригинальным текстом, а также любое представление, которое вы решили использовать для значений DateTime. Таким образом, со временем вы сможете сделать представление более "умным", чтобы охватить больше случаев, и в конечном итоге получить возможность обрабатывать что-то вроде "где-то между 1940 и 16 сентября 1945".

Первоначально вы, возможно, захотите хранить только строковое представление и два значения DateTime - самую раннюю и самую позднюю возможную дату. Это покрывает большинство случаев, с которыми вы столкнетесь, и к ним очень легко делать запросы. Вы можете оставить значение Datetime равным null или установить его на максимальное или минимальное значение, чтобы представить полубесконечные диапазоны, например, "после 1900 года".

6
ответ дан 30 November 2019 в 01:08
поделиться

Если неопределенность является двоичной (т.е. дата известна или неизвестна), я бы выбрал тип DateTime, допускающий значение NULL. В противном случае я бы подумал о создании структуры-оболочки с дополнительным свойством перечисления:

public enum DateConfidence
{
     Certain,
     Unknown,
     YearOnly,
     ApproximateYearOnly
}
2
ответ дан 30 November 2019 в 01:08
поделиться

Я бы подумал о создании класса, который обертывает DateTime (или DateTimeOffset) и имеет дополнительные поля для представления того, какие части даты верны, а какие нет.

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

11
ответ дан 30 November 2019 в 01:08
поделиться

DateTime? допускает значение NULL. Это может быть ваш лучший выбор. Другой альтернативой является DateTime.MinValue (или MaxValue ).

[Edit] На самом деле, перечитывая ваш вопрос, я думаю, что лучше всего разработать собственный класс, который будет точно соответствовать вашим целям.

1
ответ дан 30 November 2019 в 01:08
поделиться

Немного нестандартный ответ на вашу проблему.

Если вы имеете дело с неструктурированными историческими данными, как вы описываете, то я действительно записываю их в виде строки - как есть. Фактическое значение данных зависит от контекста, в котором они используются. Вы можете возразить, что мы теряем смысл, но на самом деле принудительное приведение таких данных с большим количеством нулевых/ произвольных значений к объекту DateTime так же бессмысленно. Вот пример:

  • 1910 - 1929
  • < 1960 или до 1960
  • Jul 1950 или после Jul 1950

  • 1950 - Present или 1950 - Now

Если вы не сможете учесть все возможности, раннее отображение текста периода в структурный объект типа DateTime может привести к потере данных. Возьмем в качестве примера Now/Present, это относительное значение, которое должно подставляться только тогда, когда оно используется, а не когда вы разбираете или преобразовываете значение. Как бы вы хранили данные до и после определенной даты? Конечно, при большом количестве работы по моделированию, вы можете захватить всю эту информацию в структурированном виде для всех возможностей.

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

0
ответ дан 30 November 2019 в 01:08
поделиться

Типичным примером этого может служить радиоуглеродное датирование. Вам нужен класс из двух человек. Предполагаемая дата и оценка ошибки. Последнее обычно выражается в годах, но вы можете выбрать любую единицу. Помните, что DateTime не может выражать дату до 0 г. до н.э., поэтому сделайте его простым int для года. Не делайте ничего более причудливого, чем это, угадывать правильный месяц бессмысленно для любой даты до 1000 года.

1
ответ дан 30 November 2019 в 01:08
поделиться

В .Net такого класса нет, поэтому лучше всего создать свой собственный класс с обнуляемыми свойствами, представляющими все необходимые поля даты.

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

0
ответ дан 30 November 2019 в 01:08
поделиться

Я предпочитаю в такой ситуации создать объект диапазона дат со свойством степени достоверности.

Что-то вроде:

public struct HistorialDateRange
{
    public DateTime StartDate { get; }
    public DateTime EndDate { get; }
    public double Confidence { get; } /* range [0.0, 1.0] */
}

Тогда у меня будет ряд конструкторов, которые позволят мне установить год, месяц или одну дату, каждый со значением достоверности. Уверенность дает мне "эластичное" число для нечетких сравнений.

Если я установил один день, то StartDate и EndDate должны охватывать эту дату.

Тогда вам решать, как определять сравнения между объектами HistorialDateRange . Я ожидал бы методов, которые позволят мне спросить, являются ли они отдельными, перекрывающимися и т. Д.

Надеюсь, что это поможет.

0
ответ дан 30 November 2019 в 01:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: