Precision loss when converting DateTime to Variant << Back



When converting from DateTime to Variant, you lose the millisecond part of the DateTime.

Use UI

Procedure Test
	DateTime dt
	Variant vt
	Move (CurrentDateTime()) to dt
	Move dt to vt
	Showln "DateTime " dt // DateTime 9/6/2021 9:38:13.857 AM
	Showln "Variant " vt  // Variant 9/6/2021 9:38:13 AM
	InKey FieldIndex                                         
End_Procedure

Send Test

DAW uses the API function SystemTimeToVariantTime, which ignores the millisecond part. I would consider that a bug, or at least a gotcha, because it is a reasonable assumption that you don't lose precision when you move data from and to a Variant data type. If the API call doesn't do what is expected, then DAW should write their own conversion routine for DateTime to Variant (which isn't difficult at all). Anyway, as an academic exercise, how would you keep the millisecond part when converting a DateTime to Variant?

Function DateTimeToVariant Global DateTime dt Returns Variant
	Variant vt
	Real rTime rMinSec
	Boolean bOK
	Move (DateGetMilliSecond(dt)) to rMinSec
	Move (rMinSec / Real(86400000)) to rMinSec
	Move 0 to rTime
	Move dt to vt
	Move (MemCopy(AddressOf(rTime), AddressOf(vt) + 8, 8)) to bOK
	If (rTime < 0) Move (rTime - rMinSec) to rTime
	Else Move (rTime + rMinSec) to rTime
	Move (MemCopy(AddressOf(vt) + 8, AddressOf(rTime), 8)) to bOK
	Function_Return vt
End_Function // DateTimeToVariant

There are a lot things to unpack here.
  1. Read the "Remark" section of the MSDN documentation
  2. When a DateTime is being stored in a Variant, the DateTime is converted to a "DOUBLE" (or REAL in VDF). It is stored at the offset of 8 of the address of the Variant.
  3. There are 86,400,000 milliseconds in a day (24hrs x 60mins x 60secs x 1000milliseconds)
  4. We can manipulate the content of a Variant using MemCopy since we know the offset. How did I figure out what the memory offset is? Check this out!
  5. This code is purely for academic exercise. In real life, DAW should implement this inside the VDF runtime instead.






Free Web Hosting