【问题标题】:Convert Date/Time (as Double) to struct* tm in C++在 C++ 中将日期/时间(作为双精度)转换为 struct* tm
【发布时间】:2011-01-03 17:42:14
【问题描述】:

我从 C# (DateTime.ToOADate(),它是一个 OLE 日期时间) 获得一个日期/时间作为双精度值。它包含从 1899 年 12 月 31 日起过去的日子,其中部分是一天中过去的部分。乘以 86400,我得到秒数,最后是一天的时间。

然而,获取日期更难。除了 UNIX 时间涵盖的日期(1970/01/01 到 2038/01/19)之外,我仍然没有解决方案。在此期间,可以使用 mktime() 将过去的天数转换为日期时间。

double OleDateTimeValue = 28170.654351851852; // 14.02.1977 15:42:16
struct tm * timeinfo;
int passedDays = (int)OLEDateTimeValue;

// between 1.1.1970 and 18.1.2038
if((passedDays >= 25569) && (passedDays <= 50423)) 
{
    timeinfo->tm_year = 70; //1970
    timeinfo->tm_mon = 0;
    timeinfo->tm_mday = 1 + (passedDays - 25569);
    mktime(timeinfo);
}    
else // date outside the UNIX date/time
{
}

现在,mktime() 格式化 tm 结构,使其代表请求的日期,如果值超出给定日期,则返回 -1。

是否有通用的计算方法?不幸的是,我不能使用 MFC,必须使用 Visual C++ 6.0。

谢谢, 马库斯

【问题讨论】:

  • Visual C++ 6.0 的编译器甚至不是 C++。它以可怕的方式违反了标准。在编程时请注意这一点,如果可以,请尝试升级。另外,不能使用MFC其实是幸运,而不是不幸。 :) 尽可能使用标准 C++ + Boost。

标签: c++ datetime


【解决方案1】:

相信你可以使用VariantTimeToSystemTime函数转换成SYSTEMTIME。

【讨论】:

  • 谢谢,这是最简单的方法。
【解决方案2】:

我喜欢日期转换 - 它们是一个很好的谜题!

以下代码适用于 1900-03-01 到 2100-02-28 的日期。它无法超越这些界限的原因是 1900 年和 2100 年不是闰年。这已针对 Microsoft 的 COleDateTime 进行了测试,并且每天都在该范围内匹配。

int leapDays = (int)((OleDateTimeValue + 1400) / 1461);
timeinfo->tm_year = (int)((OleDateTimeValue - leapDays - 1) / 365);
int janFirst = timeinfo->tm_year * 365 + (int)((timeinfo->tm_year + 7) / 4);
int wholeDays = (int)OleDateTimeValue - janFirst;
if (timeinfo->tm_year % 4 != 0 && wholeDays > 58)
    ++wholeDays;
static int firstOfMonth[12] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
timeinfo->tm_mon = std::upper_bound(&firstOfMonth[0], &firstOfMonth[12], wholeDays) - &firstOfMonth[0];
timeinfo->tm_mday = wholeDays - firstOfMonth[timeinfo->tm_mon - 1] + 1;

时间部分的转换是微不足道的,我把它留给读者作为练习。

【讨论】:

  • 是否有标准的方法来做这件事,或者开发者是否期望使用上面的公式?
  • @JasonThompson 可能有一种标准方式,但我不知道,否则我不会提供我所做的答案。鉴于没有其他人提供答案,这可能是不可能的。老实说,我希望 mktime 可以处理给定范围之外的日期,例如,tm_year 使用负数。
【解决方案3】:

转换为 time_t 应该很容易(乘以 86400 并添加一个常量偏移量),然后您可以使用 localtime 函数。但您仍将受限于 UNIX 时间范围。如果您确实需要超出该范围,那么 villintehaspam 的答案以及复制所有单独的字段看起来都是可行的方法。

【讨论】:

    猜你喜欢
    • 2014-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-10
    • 2015-09-09
    • 2015-05-06
    • 2019-03-18
    • 1970-01-01
    相关资源
    最近更新 更多