在C ++中将日期/时间(作为Double)转换为struct * tm

时间:2011-01-03 17:42:15

标签: c++ datetime

我从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。

谢谢, 马库斯

3 个答案:

答案 0 :(得分:3)

我相信您可以使用VariantTimeToSystemTime功能转换为SYSTEMTIME。

答案 1 :(得分:2)

我喜欢日期转换 - 他们制作了这么好的拼图!

以下是一些适用于1900-03-01至2100-02-28之间日期的代码。它不能超越这些界限的原因是1900年和2100年不是闰年。这已针对微软的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;

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

答案 2 :(得分:0)

转换为time_t应该很容易(乘以86400并添加常量偏移),然后您可以使用localtime函数。但是你仍然会受限于UNIX时间范围。如果你真的需要超出这个范围,那么villintehaspam的答案,以及复制所有单个字段,看起来就像是要走的路。