Какая структура данных рекомендуется для нескольких календарей, дат и продолжительности? - PullRequest
20 голосов
/ 25 марта 2011

У меня есть требование хранить даты и длительности, возникающие из разных календарей.В частности, мне нужно хранить даты, которые:

  1. Включают изменения в григорианские календари в разных странах в разное время
  2. Охватывают исторический период не менее 500 лет
  3. Работа с несколькими типами календаря - лунный, солнечный, китайский, финансовый, христианский, UTC, мусульманский.
  4. Сделка с изменением в Великобритании в конце года с 31 марта по 31 декабря и сопоставимымизменения в других странах.

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

У меня есть детали необходимых вычислений.Временная метка Firebird основана на функции даты, которая начинается 1 января 100 г. н.э., поэтому она не может использоваться длительно так, как мне нужно для ее записи.Кроме того, этот тип данных предназначен (как и большинство функций меток времени) для записи количества дней с базовой даты;он не предназначен для записи календарных дат.

Может кто-нибудь предложить:

  1. Структура данных для хранения дат и длительностей, соответствующих вышеуказанным требованиям ИЛИ
  2. Aссылка на такую ​​структуру данных ИЛИ
  3. Предложите рекомендации по подходу к структурированию такого хранилища ИЛИ
  4. Любые моменты, которые могут помочь мне найти решение.

РЕДАКТИРОВАТЬ:

@ Уоррен П предоставил отличную работу в своих ответах.Я, очевидно, недостаточно четко объяснил, что я ищу, поскольку его работа сосредоточена на вычислениях и на том, как их вычислять.Все ценные и полезные вещи, но не то, что я намеревался передать своим вопросом.

У меня есть детали всех вычислений, необходимых для преобразования между различными представлениями дат, и у меня есть довольно хорошее представление о том, как их реализовать (используя такие элементы, как предлагает Уоррен).Однако мое требование - хранить даты, которые соответствуют различным критериям, перечисленным выше.Пример: дата для сохранения - «Третий 13 июня Карл II».Я пытаюсь определить подходящую структуру для хранения таких дат.

РЕДАКТИРОВАТЬ:

Я исправил предложенную схему.Я перечислил атрибуты в каждой таблице и определил таблицы и атрибуты на примерах, приведенных в третьем разделе поля сущности.Я использовал пример, приведенный в этом вопросе и ответе , в своем определении за примером и изменил пример в моем вопросе для соответствия.Хотя я доказал свою схему, описав чей-то пример, эта схема все еще может быть слишком сложной;более анализируется;пропустить некоторое очевидное упрощение и может оказаться очень трудным для реализации (действительно, это может быть просто неправильно).Любые комментарии или предложения будут приветствоваться.

enter image description here

Ответы [ 2 ]

10 голосов
/ 25 марта 2011

Если вы пишете свой собственный, как я предполагаю, вы собираетесь, я бы создал класс, который содержит TDateTime и другие поля, и я бы основывал его на функциональности очень хорошо написанного расширения mxDateTime для Python, котороеявляется очень легко читаемым, открытым кодом, кодом C, который вы можете использовать для извлечения логики григорианского календаря, которая вам понадобится.

В определенных пределах TDateTime всегда прав.Это значение эпохи (0) - 30 декабря 1899 года в полночь.Оттуда вы можете рассчитать другие числа юлианского дня.Он поддерживает отрицательные значения, и, следовательно, он будет поддерживать более 400 лет.Я верю, что вы начнете вносить исправления во время последних реформ григорианского календаря.Если вы уйдете с пятницы, 15 октября 1582 года, и определите номер его юлианского дня, а также проведете реформы до и после этого, вы сможете сделать все, что вам нужно.Имейте в виду, что до 1899 года время «бежит назад», но это просто проблема человеческих голов, компьютер будет точным и вычислит количество минут и секунд, вплоть до предела с плавающей запятой двойной точностиматематика для тебяПридерживайтесь TDateTime в качестве базы.

Я нашел действительно старый код BorlandPascal / TurboPascal, который обрабатывает очень широкий диапазон дат здесь .

Если вам нужно работать с арабскими, еврейскими и другими календарями,Опять же, я отсылаю вас к Python как отличному источнику рабочих примеров.Не только расширение mxdatetime, но и такие вещи, как this .

Для сохранения базы данных вам может потребоваться, чтобы ваше хранилище дат основывалось на числах юлианских дней, а ваше время в секундах, подобных C, с полуночи, если максимальное разрешение, которое вам нужно, составляет 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 Modeling, чем я, так что если вы опубликуете эту диаграмму, я бы проголосовал за нее, и это было бы так.Что касается меня, я буду хранить три поля;Поле Datetime, которое нормализовано к современным календарным стандартам, текстовое поле (произвольная форма), содержащее исходную научную дату в любой форме, и несколько других полей, которые являются внешними ключами таблицы поиска подтипов, чтобы помочь мне упорядочить и искать по датампо дате и подтипу.Это было бы ЭТО для меня.

3 голосов
/ 25 марта 2011

Только частичный ответ, но важная часть.

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

База данных часовых поясов TZ-база данных и обертка Delphi TZDB вокруг базы данных TZ окажут большую помощь.
У него есть база данных с правилами исторического поведения часовых поясов.

Я знаю, что они основаны на текущих календарных схемах, и вам нужно сначала перейти на UTC.

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

Edit:

Схема, которую я бы использовал, была бы такой:

  • найдите способы преобразования всех ваших календарей в / из UTC
  • хранить тип календаря
  • сохраните даты в их исходном формате и источник даты (на случай, если ваш источник облажался, и вам необходимо пересчитать).
  • используйте преобразования в формате UTC для перехода от оригинала через UTC к типам календаря в вашем пользовательском интерфейсе

- Йерун

...