首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >对于多个日历、日期和持续时间,建议使用哪种数据结构?

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

Stack Overflow用户
提问于 2011-03-25 09:05:22
回答 2查看 1.6K关注 0票数 20

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

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

我还需要存储持续时间,我已经将其定义为两个时间戳(日期和时间)之间的差异。这意味着需要能够存储“零”日期-这样我就可以存储持续时间,比方说,三个半小时;或10分钟。

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

有没有人建议:

  1. 用于存储符合上述要求的日期和持续时间的数据结构或
  2. 此类数据结构的参考或
  3. 提供有关构建此类存储的指导原则或
  4. 任何可帮助我找到解决方案的要点。

编辑:

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

我确实有在不同的日期表示之间转换所需的所有计算的详细信息,并且我对如何实现它们有一个相当好的想法(使用Warren建议的元素)。但是,我的要求是存储满足上面列出的各种条件的日期。示例:要存储的日期-‘3月13日查尔斯二世’。我正在尝试确定一个适当的结构来存储这些日期。

编辑:

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-03-25 09:27:55

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

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

我发现了一些非常旧的BorlandPascal/TurboPascal代码,它们处理非常广泛的日期here

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

对于数据库持久性,如果您需要的最大分辨率是1秒,那么您可能希望以julian天数作为日期存储的基础,并将您的时间作为从午夜开始的类似C的秒数。

下面是我将开始的代码片段,并对其进行代码补全:

代码语言:javascript
复制
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建模,所以如果你发布了这张图,我会支持它,就是这样。就我而言,我将存储三个字段:一个符合现代日历标准的日期时间字段,一个包含任何形式的原始学术日期的文本字段(自由格式),以及一些其他字段,它们是子类型查找表外键,以帮助我按日期和子类型组织和搜索日期。对我来说就是这样。

票数 10
EN

Stack Overflow用户

发布于 2011-03-25 22:36:19

这只是一个部分答案,但却是一个重要的部分。

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

围绕TZ-database的时区数据库TZ-database和Delphi TZDB wrapper将会有很大帮助。

它有一个数据库,里面有关于时区历史行为的规则。

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

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

编辑:

我使用的方案是这样的:

  • 想办法让您的所有日历都可以转换为UTC
  • 存储日历类型
  • 以其原始格式存储日期和日期来源(以防源出错,您需要recalculate).
  • use UTC转换才能从原始的UTC转换为UI

中的日历类型

--jeroen

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5427459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档