When I use the following code in a newly inserted record in a TClientDataSet:
cdsMyDateField.OldValue <> Null
I get an EConvertError:
''0.0' is not a valid timestamp'.
Looking at Delphi's VCL's code, it tries to convert the value to TDateTime which results in this Exception because the value (Null) is an invalid DateTime, but as I'm comparing Variants I thought that it would return a variant, which would be Null in this case, but that doesn't happen, instead I get this exception.
I know that I can just check if the DataSet.State = dsInsert before comparing the values, as if the State = dsInsert every OldValue is Null, but I want to understand why the OldValue tries to convert the value instead of Just returning Null in all Fields when the State = dsInsert.
Can anyone please give me some light?
FWIW, I've run into this same problem and it caused me several headaches. My opinion: The behaviour is inconsistent so even from that reason alone I class it as a bug. It's also a bug because raising an exception on reading a property is IMHO ridiculous and not in keeping with the intent of properties (principle of least surprise.) I'd expect OldValue to be Unassigned, not raise an exception on read. (Also, the fact that some issue has existed for a long time does not imply anything about whether or not it's a bug.)
(Edit: Updating my answer with more information including our workaround. Also posted same to the QC report: http://qc.embarcadero.com/wc/qcmain.aspx?d=73852 )
We've also had this same problem in an app that makes heavy use of datasnap/clientdatasets. The actual problem however is not with the clientdataset, but with the Timestamp validation routine in SysUtils that apparently erroneously validates a Timestamp with a 0.0 value as invalid.
The workaround/fix is hence to SysUtils and the validation routine, and not to Tclientdataset Specifically, in the validation routine "ValidateTimeStamp()", the Time portion is correctly compared < 0 but the Date portion is erroneously compared <= 0.
Consequently a (legitimate) 0.0 Datetime value will sometimes be converted to a Timestamp with datepart = 0, and when this value is again reverse validated (such as when the value is read from a dataset field as shown here and in the QC report), an exception is (erroneously) raised. Hence the simple fix of changing the validation for the Date portion of the timestamp to use strict less-than, fixes the problem exposed by TClientDataset.
Here's our workaround, based on Delphi 7.1
(* SysUtils.pas line 10934 (Delphi 7.1) *)
(**)(* fix - Timestamp values 0.0 erroneously designated as invalid *)
(* D7.1 *)
(* Walter Prins, originally patched May 2005, submitted 4 June 2009 *)
procedure ValidateTimeStamp(const TimeStamp: TTimeStamp);
begin
if (TimeStamp.Time < 0) or (TimeStamp.Date < 0) then (* Changed TimeStamp.Date <= 0 to TimeStamp.Date < 0 *)
ConvertErrorFmt(@SInvalidTimeStamp, [TimeStamp.Date, TimeStamp.Time]);
end;