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

发布于 2024-10-26 14:25:54 字数 1401 浏览 1 评论 0原文

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

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

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

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

任何人都可以建议:

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

编辑:

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

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

编辑:

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

在此处输入图像描述

I have a requirement to store dates and durations arising from multiple different calendars. In particular I need to store dates that:

  1. Span the change to Gregorian calendars in different countries at different times
  2. Cover a historic period of at least 500 years
  3. Deal with multiple types of calendar - lunar, solar, Chinese, Financial, Christian, UTC, Muslim.
  4. Deal with the change, in the UK, of the year end from 31st March to 31st December, and comparable changes in other countries.

I also need to store durations which I have defined as the difference between two timestamps (date and time). This implies the need to be able to store a "zero" date - so I can store durations of, say, three and a half hours; or 10 minutes.

I have details of the computations needed. Firebird's timestamp is based on a date function that starts at January 1st, 100 CE, so is not capable of being used for durations in the way I need to record them. In addition this data type is geared up (like most timestamp functions) to record the number of days since a base date; it is not geared up to record calendar dates.

Could anyone suggest:

  1. A data structure to store dates and durations that meet the above requirements OR
  2. A reference to such a data structure OR
  3. Offer guidelines to approach the structuring of such storage OR
  4. Any points that may help me to a solution.

EDIT:

@Warren P has provided some excellent work in his responses. I obviously have not explained what I am seeking clearly enough, as his work concentrates on the computations and how to go about calculating these. All valuable and useful stuff, but not what I intended my question to convey.

I do have details of all the computations needed to convert between various representations of dates, and I have a fairly good idea of how to implement them (using elements such as Warren suggests). However, my requirement is to STORE dates which meet the various criteria listed above. Example: date to be stored - 'Third June 13 Charles II'. I am trying to determine an appropriate structure within which to store such dates.

EDIT:

I have amended my proposed schema. I have listed the attributes on each table, and defined the tables and attributes by examples, given in the third section of the entity box. I have used the example given in this question and answer in my definition by example, and have amended the example in my question to correspond. Although I have proved my schema by describing somebody else's example, this schema may still be over complicated; over analysed; miss some obvious simplification and may prove very difficult to implement (Indeed, it may be plain wrong). Any comments or suggestions would be most welcome.

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

但可醉心 2024-11-02 14:25:54

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

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

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

如果您需要处理阿拉伯语、犹太语和其他日历,我再次推荐您使用 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。

If you are writing your own, as I assume you intend to, I would make a class that contains a TDateTime, and other fields, and I would base it on the functionality in the very nicely written mxDateTime extension for Python, which is very easily readable, open source, C code, that you could use to extract the gregorian calendar logic you are going to need.

Within certain limits, TDateTime is always right. It's epoch value (0) is December 30, 1899 at midnight. From there, you can calculate other julian day numbers. It supports negative values, and thus it will support more than 400 years. I believe you will start having to do corrections, at the time of the last Gregorian calendar reforms. If you go from Friday, 15 October 1582, and figure out its julian day number, and the reforms before and after that, you should be able to do all that you require. Be aware that the time of day runs "backwards" before 1899, but that this is purely a problem in human heads, the computer will be accurate, and will calculate the number of minutes and seconds, up to the limit of double precision floating point math for you. Stick with TDateTime as your base.

I found some really old BorlandPascal/TurboPascal code that handles a really wide range of dates here.

If you need to handle arabic, jewish, and other calendars, again, I refer you to Python as a great source of working examples. Not just the mxdatetime extension, but stuff like this.

For database persistence, you might want to base your date storage around julian day numbers, and your time as C-like seconds since midnight, if the maximum resolution you need is 1 second.

Here's a snippet I would start with, and do code completion on:

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;

I see no reason to STORE both the julian day number, and the TDateTime, just use a constant, subtract/add from the Trunc(FBaseDateTime) value, and return that, in the GetJulianDayNumber,SetJulianDayNumber functions. It might be worth having fields where you calculate the year, month, day, for the given calendar, once, and store them, making the display as string function much simpler and faster.

Update: It looks like you're better at ER Modelling than me, so if you posted that diagram, I'd upvote it, and that would be it. As for me, I'd be storing three fields; A Datetime field that is normalized to modern calendar standards, a text field (free form) containing the original scholarly date in whatever form, and a few other fields, that are subtype lookup table Foreign keys, to help me organize, and search on dates by the date and subtype. That would be IT for me.

呢古 2024-11-02 14:25:54

虽然只是部分答案,但很重要。

由于您要在一个非常广泛的范围内存储日期,其中日历发生了很多事情,因此您需要适应这些变化。

时区数据库 TZ-database 和 Delphi 围绕 TZ 数据库的 TZDB 包装器 将提供很大帮助。
它有一个数据库,其中包含时区历史行为的规则。

我知道它们基于当前的日历方案,您需要先转换为 UTC。

您需要为您想要支持的其他日历方案设计类似的东西。

编辑:

我使用的方案如下:

  • 找到所有日历与 UTC 之间转换的方法
  • 存储日历类型
  • 以原始格式存储日期以及日期的来源(以防万一你的来源搞砸了,你需要重新计算)。
  • 使用 UTC 转换从原始的 UTC 转换为 UI 中的日历类型

--jeroen

Only a partial answer but an important piece.

Since you are going to store dates in a very broad range where a lot of things happened to calendars, you need to accommodate for those changes.

The timezone database TZ-database and the Delphi TZDB wrapper around the TZ-database will be of big help.
It has a database with rules how timezones historically behave.

I know they are based on the current calendar schemes, and you need to convert to UTC first.

You need to devise something similar for the other calendar schemes you want to support.

Edit:

The scheme I'd use would be like this:

  • find ways for all your calendars to convert to/from UTC
  • store the calendar type
  • store the dates in their original format, and the source of the date (just in case your source screwed up, and you need to recalculate).
  • use the UTC conversions to go from your original through UTC to the calendar types in your UI

--jeroen

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文