如何处理"variant time"(DATE,双精度,8 字节)?



我似乎找不到任何关于如何处理"可变时间"(DATE, double, 8字节变量)的信息....我有一个变量时间" a ",其值为"41716.892329"。如果我转换"A"使用"VariantTimeToSystemTime"(或"COleDateTime") -我得到"2014-03-18 21:24:57"。

  • 这个变量时间是如何计算的?
  • 它能够存储毫秒吗?
  • 是否有任何方法来确定变量时间是否为上午或下午时间?

我对AM/PM的事情有点困惑,因为我正在使用的设备在那一刻被设置为"09:24:57"(AM)而不是"21:24:57"(PM)。

这可能是设备SDK的问题,为我提供了一个不正确的变体时间?

EDIT:这是设备中时区设置不正确的问题(被设置为"GMT-12:00"而不是"GMT-00:00")

谢谢。

<;(DATE)与Excel DATE几乎相同,但又不完全相同。Excel(因为它最初与Lotus-123竞争)复制了Lotus存储日期的方式(为了与现有用户兼容)。不幸的是,Lotus有一个bug(可能是故意的,参见Joel Spolsky的博客),这意味着1900年2月有29天。因此,Excel也认为1900年2月有29天(仍然)。尝试将值60格式化为日期。然而,OLE Automation(不只是在Excel中)使用了"可变时间",并且对其进行了修复,以便可以正确地表示任何时间点,最初是在1753年1月1日到2078年12月31日之间(ca)。 2006),但现在是在100年1月1日和9999年12月31日(12/05/2018)之间,这样可以通过简单的(可能是两部分,见下文)减法获得时差。

Eric Lippert有一个全面的分析,但总结是:

"变量时间"是一个双精度数,其中整数部分是 30dec1899之后的天数。因此,0是30dec1899,而01jan1900实际上是2(不像Excel复制Lotus并将其定义为第1天),并且没有29feb1900。十进制字符串表示的小数部分被视为从当天00:00:00开始的无符号部分日偏移量。这里的措辞的意义在于,虽然数字-1.75与-1 + -0.75相同,但一种不同的时间将-1.75视为-1 + +0.75(即午夜29dec1899之后一天的3/4)。因此,在将负值转换为YYYY/MM/DD HH:MM:SS或计算涉及负值的日期差异时,必须分别处理日期和时间部分。

好了,我想我已经找到所有的答案了!正如Simon Mourier所评论的,"41716.892329"实际上是"2014-03-18 21:24:57",这就是为什么——它看起来像这样分割了不同的时间:"(日期) 41716。时间() 892329"。如果你用"0.892329"乘以24.0,我们将得到21,415896,其中"21"是我的小时值。

我在这里找到了一些关于如何计算这个变量时间的信息:http://doxygen.reactos.org/df/d85/variant_8c_source.html -(在"VarUdateFromDate"函数中)

看起来变量时间能够处理毫秒,它只是像"VariantTimeToSystemTime"这样的函数忽略了它们(可能是由于缺乏精度原因?)。函数仅舍入毫秒,如果需要,将日期时间向前调整。(所以如果我们有输入时间"21:24:57。567年",输出时间将"21:24: 58

在这里发现了一些有趣的材料:http://www.codeproject.com/Articles/17576/SystemTime-to-VariantTime-with-Milliseconds -"SystemTime到VariantTime与毫秒"。

变量中的日期/时间格式与Excel中的日期/时间格式相同。

这里是一个简短的视图如何计算:

小数分隔符前的部分指定日期,小数分隔符后的部分指定时间。

基数为1900-01-01 00:00:00,值为1。所以1900-01-02 00:00:00的值是2,以此类推,只有一个小小的例外:值60表示日期1900-02-29,这个日期不存在(1900不是闰年)。

Values>= 0 and <指定没有日期关系的时间。小于0的值是未定义的。>

时间被简单地分成天。小时/24,分钟/24/60,秒/24/60/60.

未保存时区信息。

毫秒通常不使用,但可以存储。

在c++ 20中,可以通过以下方式将其转换为time_point<system_clock, milliseconds>:

using namespace std::chrono;
using ddays = duration<double, days::period>;
constexpr auto tp = round<milliseconds>(
   sys_time{ddays{41716.892329}} - (sys_seconds{} - sys_days{December/30/1899}));
static_assert(tp == sys_days{2014y/3/18} + 21h + 24min + 57s + 226ms);

在这个范围内(从1899年12月30日开始),double的精度约为半微秒。

这是我用来计算时间部分(包括毫秒)的公式。请注意,如果您计划计算毫秒数,那么将毫秒数四舍五入是很重要的。

    double date = var.date;
    double hours = (date - floor(date)) * 24;
    double minutes = (hours - floor(hours)) * 60;
    double seconds = (minutes - floor(minutes)) * 60;
    double milliseconds = round((seconds - floor(seconds)) * 1000);

都是double类型,因此要得到最终的数字,将它们都转换为int类型。我知道这是一个老问题,但可能对某些人有用

相关内容

  • 没有找到相关文章

最新更新