我正在使用XMLTimeToDateTime作为JSON中datetime字段的时间转换函数。我看到这个功能意外转换。它似乎尝试将某种UTC时间用于本地时间转换,即使你告诉它不要。
这是一些测试代码(在DUnit中):
uses
System.SysUtils,
Soap.XSBuiltIns,
System.DateUtils;
procedure TestXMLTimeConversion.TestXMLTimeToDateTime;
var
ReturnValue: TDateTime;
testDate: TDateTime;
begin
testDate := EncodeDateTime(2014, 3, 2, 3, 12, 45, 0);
ReturnValue := XMLTimeToDateTime('2014-03-02T03:12:45', False);
CheckEquals(testDate, ReturnValue, 'ReturnValue: ' + FormatDateTime('yyyy-mm-dd"T"hh:nn:ss', ReturnValue));
end;
返回
ReturnValue: 2014-03-02T04:12:45, expected: <41700,1338541667> but was: <41700,1755208333>
如果将XMLTimeToDateTime的布尔参数更改为True,则转换将变为正确。我原本预计会出现相反的情况。我在这里误解了什么吗?
编辑:
我挖了一下,我相信我找到了原因。根据我在互联网上找到的varius ISO8601配置文件的规范,其中一个是this one from W3,似乎系统可能希望时区指示在指定时间戳时始终可用。如果您将时区指示附加到测试用例,它会计算正确的时间(在这种情况下,我会调整为CET)。
procedure TestTXSDateTime.TestXMLTimeToDateTimeWithTimeZone;
var
ReturnValue: TDateTime;
testDate: TDateTime;
begin
testDate := EncodeDateTime(2014, 3, 2, 3, 12, 45, 0);
ReturnValue := XMLTimeToDateTime('2014-03-02T03:12:45+01:00', False);
CheckEquals(testDate, ReturnValue, 'ReturnValue: ' + FormatDateTime('yyyy-mm-dd"T"hh:nn:ss', ReturnValue));
end;
这样就没有指定时间戳。这应该是合法的,我希望这会导致datetime值的分数设置为0,无论你在哪个时区。
procedure TestTXSDateTime.TestXMLDateToDateTime;
var
ReturnValue: TDateTime;
testDate: TDateTime;
begin
testDate := EncodeDateTime(2014, 3, 2, 0, 0, 0, 0);
ReturnValue := XMLTimeToDateTime('2014-03-02', False);
CheckEquals(testDate, ReturnValue, 'ReturnValue: ' + FormatDateTime('yyyy-mm-dd"T"hh:nn:ss', ReturnValue));
end;
然而,在这种情况下,XMLTimeToDateTime仍会针对本地偏差进行调整,在我看来这是一个错误。如果您居住在美国或其他任何落后于UTC的地方,则意味着您获得的TDateTime值的日期部分对应于实际给出的前一天。