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.
- Read the "Remark" section of the MSDN documentation
- 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.
- There are 86,400,000 milliseconds in a day (24hrs x 60mins x 60secs x 1000milliseconds)
- 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!
- This code is purely for academic exercise. In real life, DAW should implement this inside the VDF runtime instead.