delphi - 对于多个日历、日期和持续时间,建议使用什么数据结构?

标签 delphi datetime date calendar firebird

我需要存储多个不同日历产生的日期和持续时间。特别是我需要存储以下日期:

  1. 跨越不同国家/地区不同时间对公历的更改
  2. 涵盖至少 500 年的历史时期
  3. 处理多种类型的历法 - 农历、阳历、农历、财经历、基督教历、UTC 历、穆斯林历。
  4. 应对英国从 3 月 31 日到 12 月 31 日的年终变化以及其他国家/地区的类似变化。

我还需要存储我定义为两个时间戳(日期和时间)之间的差异的持续时间。这意味着需要能够存储“零”日期 - 因此我可以存储三个半小时的持续时间;或 10 分钟。

我有details所需的计算。 Firebird 的时间戳基于从公元 100 年 1 月 1 日开始的日期函数,因此无法按照我需要记录的方式用于持续时间。此外,这种数据类型(像大多数时间戳函数一样)可以记录自基准日期以来的天数;它不适合记录日历日期。

有人可以建议吗:

  1. 用于存储满足上述要求的日期和持续时间的数据结构或
  2. 对此类数据结构的引用或
  3. 提供此类存储结构的指南或
  4. 任何可以帮助我找到解决方案的要点。

编辑:

@Warren P 在他的回复中提供了一些出色的工作。显然我还没有足够清楚地解释我正在寻求什么,因为他的工作集中在计算以及如何进行计算上。所有有值(value)且有用的东西,但不是我想要表达的问题。

我确实拥有在各种日期表示形式之间进行转换所需的所有计算的详细信息,并且我非常清楚如何实现它们(使用 Warren 建议的元素)。但是,我的要求是存储满足上面列出的各种标准的日期。示例:要存储的日期 - “Third June 13 Charles II”。我正在尝试确定一个适当的结构来存储此类日期。

编辑:

我修改了我提议的架构。我列出了每个表上的属性,并通过示例定义了表和属性,在实体框的第三部分中给出。我已经使用了此 question 中给出的示例和 answer在我的定义中通过示例,并修改了我的问题中的示例以进行对应。虽然我已经通过描述别人的例子证明了我的模式,但这个模式可能仍然过于复杂;过度分析;错过一些明显的简化,可能会很难实现(事实上,这可能是完全错误的)。欢迎任何意见或建议。

enter image description here

最佳答案

如果您正在编写自己的代码(正如我假设您打算这样做),我将创建一个包含 TDateTime 和其他字段的类,并且我将其基于编写得非常好的 Python mxDateTime 扩展中的功能,该扩展是非常容易阅读的开源 C 代码,您可以使用它来提取您需要的公历逻辑。

在一定范围内,TDateTime 总是正确的。它的纪元值 (0) 是 1899 年 12 月 30 日午夜。从那里,您可以计算其他儒略日数字。它支持负值,因此将支持超过 400 年。我相信在上次公历改革时,您将开始不得不进行更正。如果你从 1582 年 10 月 15 日星期五开始,算出它的儒略日数,以及在此之前和之后的改革,你应该能够完成你所要求的一切。请注意,一天中的时间在 1899 年之前是“向后”运行的,但这纯粹是人类头脑的问题,计算机会很准确,并且会计算分钟和秒数,直至 double 浮点的限制数学给你。坚持以 TDateTime 作为基础。

我发现了一些非常古老的 BorlandPascal/TurboPascal 代码,可以处理非常广泛的日期 here .

如果您需要处理阿拉伯语、犹太语和其他日历,我再次建议您使用 Python 作为工作示例的重要来源。不仅仅是 mxdatetime 扩展,还有像 this 这样的东西.

对于数据库持久性,如果您需要的最大分辨率是 1 秒,您可能希望将日期存储基于儒略日数字,并将时间设置为自午夜以来类似 C 的秒数。

这是我将开始的代码片段:

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 建模,所以如果你发布该图,我会投票,仅此而已。对于我来说,我会存储三个字段;一个按照现代日历标准标准化的日期时间字段,一个包含任何形式的原始学术日期的文本字段(自由格式),以及一些其他字段,它们是子类型查找表外键,以帮助我组织和搜索日期按日期和子类型。这对我来说就是 IT。

关于delphi - 对于多个日历、日期和持续时间,建议使用什么数据结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5427459/

相关文章:

php - 从Unix时间戳创建PHP DateTime对象,在一行中设置时区

c# - 为什么 DateTime.ToLocalTime() 不考虑夏令时?

javascript - 在JS中将以下日期格式化为YYYY-mm-dd

delphi - 我需要在派生类的构造函数声明之后放置重载或覆盖字吗?

c# - DateTime.TryParseExact 格式 MM/dd/yyyy

java - 收集一段时间内每个月的天数

java - 使用 new Date(aDate.getTime() + aTime.getTime()) 创建 Java 日期时忽略夏令时

德尔福: Char value for newline

c# - 防篡改表

delphi - 如何使用 LiveBindings 在 TStringGrid 中显示超过 200 行?