次のように、Delphi 2009 update 2 および Delphi 2007 で再現しました。
uses DB, DBClient;
procedure TTestForm1.TestButtonClick(Sender: TObject);
const
SMyDateField = 'MyDateField';
SMyIntegerField = 'MyIntegerField';
var
MyClientDataSet: TClientDataSet;
MyClientDataSetMyDateField: TField;
MyClientDataSetMyIntegerField: TField;
OldValue: Variant;
begin
MyClientDataSet := TClientDataSet.Create(Self);
MyClientDataSet.FieldDefs.Add(SMyDateField, ftDate);
MyClientDataSet.FieldDefs.Add(SMyIntegerField, ftInteger);
MyClientDataSet.CreateDataSet();
MyClientDataSetMyDateField := MyClientDataSet.FieldByName(SMyDateField);
MyClientDataSetMyIntegerField := MyClientDataSet.FieldByName(SMyIntegerField);
MyClientDataSet.Insert();
OldValue := MyClientDataSetMyIntegerField.OldValue;
OldValue := MyClientDataSetMyDateField.OldValue;
end;
常に次のエラーが発生します。
exception class EConvertError with message ''0.0' is not a valid timestamp'.
これがバグとみなされるかどうかはわかりません:
- 挿入時に技術的には OldValue がないため、取得すると例外が発生する可能性があります
- MyClientDataSetMyIntegerField.OldValue は 0 を返しますが、MyClientDataSetMyDateField.OldValue は例外を発生させます
その他の注意事項:
- TCustomClientDataSet.GetFieldData は実際の基になるデータを取得します
- TDataSet.DataConvert は、基になるデータをネイティブ データ形式に変換し、必要に応じて有効性チェックを実行します。
編集: Fabricio のコメントの結果として、挿入後に OldValue が技術的に無効であることを強調しました。技術的には、これはバグではないかもしれません。
彼の「新しい証拠」は、VCL/RTL ソースを確認することで確認できます。
フィールド タイプが ftDate、ftTime、ftDateTime の場合、TDataSet.DataConvert は、TimeStamp を埋めるローカルの NativeToDateTime 関数を呼び出します。次に、SysUtils.TimeStampToDateTime を使用してそれを変換します。SysUtils.TimeStampToDateTime は、SysUtils.ValidateTimeStamp を呼び出します。この関数は、時刻部分が 0 未満の場合に例外を発生させます。日付部分がゼロ以下です。
Date 部分は、フィールド タイプ ftDate および ftDateTime (TDateField および TDateTimeField) の場合にのみゼロになる可能性があるため、それらのみが例外を発生させることができます。他のすべてのデータ型の場合、NativeToDateTime には問題はありません。これらの型はすべて、ゼロバイトで埋められた結果を許可します。
RTL/VCL の履歴を確認しました。Delphi 6 の SysUtils.TimeStampToDateTime は SysUtils.ValidateTimeStamp を呼び出すため、この動作は 2001 年から同じです。
そのため、これをバグと見なすことは非常に困難です。