#1 2026-02-25 08:34:23

Mr.Ed
Member
Registered: 2020-04-09
Posts: 6

wrong Iso8601ToDateTime conversion

I get wrong result if dates include time values.

  ShowMessage(DateTimeToIso8601Text(Iso8601ToDateTime('1492-10-12T16:00:00')));
  // results in '1492-10-13T08:00:00'

The fractional time part is always added in Iso8601ToDateTimePUtf8CharVar but should be subtracted if the date is a negative number.

Offline

#2 2026-02-25 20:50:40

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,410
Website

Re: wrong Iso8601ToDateTime conversion

Values before TDateTime = 0 are just not supported.

Offline

#3 2026-02-25 21:13:52

rvk
Member
Registered: 2022-04-14
Posts: 159

Re: wrong Iso8601ToDateTime conversion

ab wrote:

Values before TDateTime = 0 are just not supported.

In that case you might want to add an assert (or other check/exception) for that ?
(That would be the easiest)

Maybe someone can suggest a patch for TDateTime < 0 if needed and accepted.

Offline

#4 Yesterday 13:22:16

Mr.Ed
Member
Registered: 2020-04-09
Posts: 6

Re: wrong Iso8601ToDateTime conversion

rvk wrote:

Maybe someone can suggest a patch for TDateTime < 0 if needed and accepted.

The mormot framework is a swiss army knife. Could just be some kind of sharpening.
Date values < 0 are supported as long as they do not have a time part.

Date is integer part and time value is fractional part of a TDateTime. Thus, values between 0.0 and -1.0 are not valid dates.

You can split a TDateTime to date with Int(x) and time with Frac(x). To put date and time together, you can add date and time, but need to subtract time from date, if date is a negative number.

The functions EncodeDateTime and Iso8601ToDateTimePUtf8CharVar in mormot.core.datetime always add the time part. I just would like to see that ObjectToJson and JsonToObject work as expected.

I would suggest to change the last line in Iso8601ToDateTimePUtf8CharVar to

  result := result + (1.0 - ((Int64(result) shr 63) shl 1)) *
                     (h * MilliSecsPerHour +
                      mi * MilliSecsPerMin +
                      ss * MilliSecsPerSec + ms) / MilliSecsPerDay;

Offline

#5 Yesterday 21:25:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 15,410
Website

Re: wrong Iso8601ToDateTime conversion

(1.0 - (Int64(result) shr 63)) is a pretty weird expression - I am not sure Int64(result) works on all compilers and targets.

I suspect a good "if result < 0" could be faster and more explicit, couldn't be?

Offline

#6 Today 08:17:21

Mr.Ed
Member
Registered: 2020-04-09
Posts: 6

Re: wrong Iso8601ToDateTime conversion

ab wrote:

(1.0 - (Int64(result) shr 63)) is a pretty weird expression - I am not sure Int64(result) works on all compilers and targets.

I suspect a good "if result < 0" could be faster and more explicit, couldn't be?

Thought, a branchless solution could be more acceptable. But yes indeed, "if result < 0" would be more explicit and cheaper at that point.

Offline

Board footer

Powered by FluxBB