我需要从一个Pascal TDateTime对象,这是一个双精度值转换为Unix纪元使用c++。
提出了一种可能的解决方案(https://forextester.com/forum/viewtopic.php?f=8&t=1000):
unsigned int UnixStartDate = 25569;
unsigned int DateTimeToUnix(double ConvDate)
{
return((unsigned int)((ConvDate - UnixStartDate) * 86400.0));
}
但是,此转换代码会产生如下错误:
T日期时间时间值= 37838.001388888886(2003年8月5日02:00)
这将转换为Unix纪元1060041719(05.08.2003 00:01:59),这显然是不正确的。
如何准确地转换此TDateTime值?
2条答案
按热度按时间jogvjijk1#
Delphi /CBuilder RTL中有一个
DateTimeToUnix()
函数就是用于此目的的。在
TDateTime
中,整数部分是December 30 1899
中的天数,小数部分是00:00:00.000
中的时间。由于floating-point math is inaccurate,使用包含不止一整天的原始数学可能会有点棘手。例如,
0.001388888886
并不完全等于00:02:00
,它更接近于00:01:59.999
。因此,您遇到了舍入问题,这正是您必须注意的问题。TDateTime
具有毫秒精度,一天中有86400000
毫秒,因此.001388888886
等于00:00:00.000
之后的119999.9997504
毫秒。如果这些毫秒被舍位为119999
,则该值为00:01:59
,或者如果它们被上舍入为120000
,则该值为00:02:00
。RTL在
TDateTime
上停止使用浮点运算是因为几年前会有细微的精度损失。现在的TDateTime
操作会在TTimeStamp
上来回运行以避免这种情况。由于您尝试在RTL之外执行此操作,因此您需要在代码中实现相关算法。您所展示的算法是许多年前RTL * 如何使用 * 将
TDateTime
转换为Unix时间戳的,但现在已经不是这样了。当前的算法看起来更像这样(从最初的Pascal转换为C):请注意我在
DateTimeToTimeStamp()
中的注解。我不确定std::round()
是否对所有值都产生 * 完全 * 相同的结果。您必须用它进行实验。