Какая структура данных рекомендуется для нескольких календарей, дат и продолжительности?
У меня есть требование хранить даты и длительности, связанные с несколькими разными календарями. В частности, мне нужно сохранить даты, которые:
- Разделите изменения на григорианские календари в разных странах в разное время.
- Накрыть исторический период не менее 500 лет.
- Работайте с несколькими типами календарей - лунными, солнечными, китайскими, финансовыми, христианскими, UTC, мусульманами.
- Сменим изменения в Великобритании на конец года с 31 марта по 31 декабря и сопоставимые изменения в других странах.
Мне также нужно сохранить длительности, которые я определил как разницу между двумя временными метками (дата и время). Это подразумевает необходимость сохранения "нулевой" даты - поэтому я могу хранить длительности, скажем, три с половиной часа; или 10 минут.
У меня детали необходимых вычислений. Временная метка Firebird основана на функции даты, которая начинается с 1 января 100 года н.э., поэтому не может использоваться для продолжительности в том, как мне нужно записывать их. Кроме того, этот тип данных настроен (как и большинство функций timestamp) для записи количества дней с базовой даты; он не предназначен для записи календарных дат.
Может ли кто-нибудь предложить:
- Структура данных для хранения дат и продолжительности, соответствующих вышеуказанным требованиям ИЛИ
- Ссылка на такую структуру данных OR
- Предлагайте рекомендации для подхода к структурированию такого хранилища ИЛИ
- Любые пункты, которые могут помочь мне в решении.
EDIT:
@Warren P предоставил отличную работу в своих ответах. Я, очевидно, не объяснил, что я ищу достаточно ясно, поскольку его работа концентрируется на вычислениях и способах их вычисления. Все ценные и полезные вещи, но не то, что я хотел рассказать.
У меня есть детали всех вычислений, необходимых для преобразования между различными представлениями дат, и у меня есть довольно хорошее представление о том, как их реализовать (используя такие элементы, как предлагает Уоррен). Тем не менее, мое требование заключается в датах STORE, которые отвечают различным критериям, перечисленным выше. Пример: дата, которую нужно сохранить - "Третий 13 июня Карл II". Я пытаюсь определить подходящую структуру, в которой можно хранить такие даты.
EDIT:
Я внесла поправки в предложенную мной схему. Я перечислил атрибуты в каждой таблице и определил таблицы и атрибуты примерами, указанными в третьем разделе окна сущности. Я использовал пример, приведенный в этом question и ответе в моем определении на примере, и внеся поправки пример в моем вопросе, чтобы соответствовать. Хотя я доказал свою схему, описав какой-то другой пример, эта схема все еще может быть сложной; над анализом; пропустите некоторое очевидное упрощение и может оказаться очень трудным для реализации (действительно, это может быть неправильно). Любые комментарии или предложения были бы наиболее желанными.
![enter image description here]()
Ответы
Ответ 1
Если вы пишете свои собственные, как я предполагаю, вы намереваетесь, я бы сделал класс, содержащий TDateTime, и другие поля, и я бы основал его на функциональности в очень красиво написанном расширении mxDateTime для Python, который очень легко читаемый, с открытым исходным кодом, C-код, который вы можете использовать для извлечения gregorian логики календаря, который вам понадобится.
В определенных пределах TDateTime всегда прав. Это значение эпохи (0) - 30 декабря 1899 года в полночь. Оттуда вы можете рассчитать другие числа юлианских дней. Он поддерживает отрицательные значения, и, следовательно, он будет поддерживать более 400 лет. Я считаю, что вы начнете делать исправления во время последних реформ в григорианском календаре. Если вы отправитесь с пятницы, 15 октября 1582 года, и выясните его число юлианских дней, а также реформы до и после этого, вы сможете сделать все, что вам нужно. Имейте в виду, что время дня работает "назад" до 1899 года, но это чисто проблема в головах человека, компьютер будет точным и рассчитает количество минут и секунд до предела с плавающей запятой двойной точности математика для вас. Придерживайтесь TDateTime в качестве базы.
Я нашел действительно старый код BorlandPascal/TurboPascal, который обрабатывает действительно широкий диапазон дат здесь.
Если вам нужно обрабатывать арабские, еврейские и другие календари, я снова отсылаю вас к Python как к большому источнику рабочих примеров. Не только расширение mxdatetime, но и прочее, например .
Для сохранения базы данных вы можете захотеть основать хранилище данных по дням в julian day numbers и ваше время как C-like секунд с полуночи, если максимальное разрешение вам нужно 1 секунду.
Вот фрагмент, с которого я начну, и завершение кода:
TCalendarDisplaySubtype = ( cdsGregorian,cdsHebrew,cdsArabic,cdsAztec,
cdsValveSoftwareCompany, cdsWhoTheHeckKnows );
TDateInformation = class
private
FBaseDateTime:TDateTime;
FYear,FMonth,FDay:Integer; // if -1 then not calculated yet.
FCalendarDisplaySubtype:TCalendarDisplaySubtype;
public
function SetByDateInCE(Y,M,D,h,m,s:Integer):Boolean;
function GetAsDateInCE(var Y,M,D,h,m,s:Integer):Boolean;
function DisplayStr:String;
function SetByDateInJewishCalendar( ... );
property BaseDateTime:TDateTime read FDateTime write FDateTime;
property JulianDayNumber:Integer read GetJulianDayNumber write SetJulianDayNumber;
property CalendarDisplaySubType:TCalendarDisplaySubtype;
end;
Я не вижу причин для того, чтобы хранить как день юлианского дня, так и TDateTime, просто используйте константу, вычитайте/добавьте из значения Trunc (FBaseDateTime) и верните это в функции GetJulianDayNumber, SetJulianDayNumber. Возможно, стоит иметь поля, где вы вычисляете год, месяц, день, для данного календаря, один раз и сохраняете их, делая дисплей как функцию строки намного проще и быстрее.
Обновление: похоже, что вы лучше в моделировании ER, чем я, поэтому, если вы разместите эту диаграмму, я бы ее повысил, и это было бы так. Что касается меня, я бы сохранил три поля; Поле Datetime, нормализованное к современным стандартам календаря, текстовое поле (свободная форма), содержащее исходную научную дату в любой форме и несколько других полей, которые представляют собой таблицу подтипов внешних ключей, чтобы помочь мне организовать и выполнить поиск по датам по дате и подтипу. Это было бы для меня.
Ответ 2
Только частичный ответ, но важная часть.
Поскольку вы собираетесь хранить даты в очень широком диапазоне, где многое происходило с календарями, вам необходимо учитывать эти изменения.
База данных часовых поясов TZ-база данных и Delphi TZDB-обертка вокруг базы данных TZ окажет большую помощь.
У этого есть база данных с правилами, как исторически ведут себя хронометры.
Я знаю, что они основаны на текущих схемах календаря, и вам нужно сначала конвертировать в UTC.
Вам нужно разработать нечто подобное для других схем календаря, которые вы хотите поддержать.
Edit:
Схема, которую я использовал бы, будет такой:
- найти способы конвертации всех ваших календарей в/из UTC
- сохранить тип календаря
- сохраните даты в их исходном формате и источник даты (на случай, если ваш источник испорчен, и вам нужно пересчитать).
- используйте конверты UTC, чтобы перейти от вашего оригинала через UTC к типам календаря в пользовательском интерфейсе.
- Йерун