json - 为什么 TFDBatchMove 为值为“03/11/2019”的日期字段引发异常 ELocalTimeInvalid?
问题描述
我在 Windows 7 SP1 机器上使用 Delphi 10.3 Rio Update 1。
我的程序的目的是将 aTFDMemtable
转换为 JSON 格式。由于我无法理解的原因,当 this 的 date 字段TFDMemTable
具有 value'03/11/2019'
时,使用 DisplayFormat"day/month/year"
会引发异常:
Project ProjMemtabJSON.exe 引发异常类 ELocalTimeInvalid 并显示消息“给定的“03/11/2019”当地时间无效(位于 DST 之前的缺失时段内)。
任何其他日期都可以"Nov, 3rd 2019"
正常工作。
我不知道这里发生了什么!
program ProjMemtabJSON;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Classes,
System.JSON,
FireDAC.Comp.DataSet,
FireDAC.Comp.Client,
FireDAC.Comp.BatchMove,
FireDAC.Comp.BatchMove.DataSet,
FireDAC.Comp.BatchMove.JSON,
Data.DB;
Var
Fmemtable : TFDmemtable ;
FJSONArray : TJSONArray;
FDBatchMoveJSONWriter1 : TFDBatchMoveJSONWriter;
FDBatchMoveDataSetReader1 : TFDBatchMoveDataSetReader;
FDBatchMove1 : TFDBatchMove;
procedure CreateMemtable;
begin
Fmemtable := TFDmemtable.Create(nil);
FMemTable.FieldDefs.Add('ID', ftInteger, 0, False);
FMemTable.FieldDefs.Add('Name', ftString, 20, False);
FMemTable.FieldDefs.Add('Status', ftString, 20, False);
FMemTable.FieldDefs.Add('Duedate', ftdatetime,0, False);
FMemTable.CreateDataSet;
end;
procedure FillMemtable;
begin
FMemtable.Append;
FMemtable.Fields[0].Value := 10; // ID
FMemtable.Fields[1].Value := 'John'; // Name
FMemtable.Fields[2].Value := 'Active'; // Status
{ ==> HERE IS THE PROBLEM : change this date to 03/11/2019 i.e. 03/Nov/2019 and an error will raise }
FMemtable.Fields[3].Value := StrToDate('02/11/2019'); // Due date dd/mm/yyyy
end;
procedure PrintMemtable;
begin
writeln('ID : ' ,Fmemtable.Fields[0].AsString);
writeln('Name : ' ,Fmemtable.Fields[1].AsString);
writeln('Status : ' ,Fmemtable.Fields[2].AsString);
writeln('Due Date : ' ,Fmemtable.Fields[3].AsString);
end;
function TableToJson : TJSONArray;
begin
Result := TJSONArray.Create;
try
FDBatchMoveDataSetReader1 := TFDBatchMoveDataSetReader.Create(nil);
FDBatchMoveJSONWriter1 := TFDBatchMoveJSONWriter.Create(nil);
FDBatchMove1 := TFDBatchMove.Create(nil);
FDBatchMove1.Reader := FDBatchMoveDataSetReader1 ;
FDBatchMove1.Writer := FDBatchMoveJSONWriter1;
try
if not FMemtable.Active then
FMemtable.Active := True;
FDBatchMoveDataSetReader1.DataSet := FMemtable;
FDBatchMoveJSONWriter1.JsonArray := Result;
FDBatchMove1.Execute;
except
on E: Exception do
raise Exception.Create('Error Message: ' + E.Message);
end;
finally
FDBatchMoveDataSetReader1.Free;
FDBatchMoveJSONWriter1.Free;
FDBatchMove1.Free;
end;
end;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
Creatememtable;
FillMemtable;
PrintMemtable;
FJSONArray := TableToJSON;
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
解决方案
有一个System.DateUtils
例程可以检查无效时间:
TTimeZone.IsInvalidTime(const ADateTime : TDateTime) : Boolean;
如果您添加DateUtils
到您的Uses
子句,则将您的 FillMemTable 更新为:
procedure FillMemtable;
var MyDate : tDateTime;
begin
FMemtable.Append;
FMemtable.Fields[0].Value := 10; // ID
FMemtable.Fields[1].Value := 'John'; // Name
FMemtable.Fields[2].Value := 'Active'; // Status
{ ==> HERE IS THE PROBLEM : change this date to 03/11/2019 i.e. 03/Nov/2019 and an error will raise }
MyDate := StrToDate('03/11/2019');
if TTimeZone.local.IsInvalidTime(MyDate) then MyDate := MyDate + 0.5; //noon won't be invalid
FMemtable.Fields[3].Value := MyDate; // Due date dd/mm/yyyy
end;
或者,如评论中所述,如果您不希望 IF 语句的开销,只需强制所有日期为中午。
我从来没有意识到有时区在午夜切换到/从 DST。不幸的是,如何定义日期(没有时间)。
推荐阅读
- r - R 中的每种数据类型在内存中需要多少空间?哪个是最小的?
- esp32 - ESP32 toit 配置失败
- javascript - 每次调用函数时如何动态更改元素的宽度?
- javascript - 在JS中通过条件映射来转换数组
- firebase - @firebase/firestore:Firestore (8.3.3):无法访问 Cloud Firestore 后端
- c++ - 关闭 switch/do 循环 C++
- json - 拆分包含数组的 Json 文件,以使用 Azure 数据流将每个数组存储在 Sql 表中
- wix - 有什么方法可以在 wix 引导程序应用程序的日志文件中隐藏变量的日志记录
- java - 矩阵的边界不适合java中给出的顶点数
- python - Selenium 与 python 没有找到特定的链接