Unexpected behavior in orekit.pyhelpers datetime - AbsoluteDate conversion

Hello,

I am using Orekit Python Wrapper for Orekit version v12.1.2 and I have noticed an unexpected behaviour when using the orekit.pyhelpers methods to map Python datetime objects to Orekit AbsoluteDate and then back to Python datetime objects. Below you can find an example and its output.

import datetime as dt
from orekit import pyhelpers

epoch = dt.datetime(2020, 1, 1, 12, 0, 59, 605000)
epoch_orekit = pyhelpers.datetime_to_absolutedate(epoch)
epoch_mapped_back = pyhelpers.absolutedate_to_datetime(epoch_orekit)

print(f"epoch: {epoch}")
print(f"epoch_orekit: {epoch_orekit}")
print(f"epoch_mapped_back: {epoch_mapped_back}")
print(f"Evaluation 1: {epoch == epoch_mapped_back}")
print(f"Evaluation 2: {epoch == epoch_mapped_back + dt.timedelta(microseconds=1)}")

As you can see from the output, I would have expected Evaluation 1 to evaluate to True and Evaluation 2 to evaluate to False. However, it seems that for some cases the mapping between Python datetime objects and Orekit AbsoluteDate is inaccurate by 1 microsecond. I did some investigation (I have also looked into this thread Datetime and Absolutedate conversions in python wrapper) and I think the cause of this behaviour is a casting performed in the orekit.pyhelpers.absolutedate_to_datetime() method.

Specifically, at line 142, rather than casting to the int type as
microseconds = int(1000000.0 * (seconds - math.floor(seconds)))
I would suggest rounding (or doing a similar operation) as
microseconds = round(1000000.0 * (seconds - math.floor(seconds)))

My questions are:

  1. Do you think this could improve the conversion accuracy in specific circumstances for version 12.1.2 (in v13, the pyhelpers have a different implementation when mapping AbsoluteDate objects to datetime objects, according to the discussion in Datetime and Absolutedate conversions in python wrapper)?
  2. Is there a specific reason for your choice of using the casting to int type rather than the rounding? I am asking this because it could be that what I am suggesting may improve the accuracy in some scenarios and worsen it in others that you may have already considered.

Thanks in advance for your support!

Best,
Gianmario

Hi Gianmario!

You are complete right, this is a quite unexpected and somewhat problematic area. Part of the problem is the use of floats as representations. You have already identified the recent previous discussion and the much improved v13 (imho). But going from datetime - absolutedate - datetime, the user should expect it to be identical. The opposite conversion chain (absolutedate - datetime -absolutedate) is not true as there is more precision in absolutedate.

The rounding issue was highlighted in Rounding error in datetime conversion . I thought there was a reason that we kept int, but cannot find any now, it seems better to use rounding, yes. But the best would probably be to avoid floats at all and use similar approach as in v13 to take the microseconds which are native python stored as ints.

Hi Petrus,

Thanks for all the clarifications!

Do you plan to release a patch also for version 12.1.2?

Best,
Gianmario

Hi Gianmario,

I have not planned a patch release for 12 series (would be based on 12.2 in that case), but if you have an interest we can? Are you on the JCC or jpype version of orekit? But I would recommend considering moving to the 13.X series if possible.

Greetz

Hi Petrus,

Thanks for asking! Nevertheless, I am considering moving to the 13.X series as you recommended. If really necessary, I can try to compile a version myself with the new pyhelpers for v12.1.2.

Thanks again for all the support, wish you a great day!

Best,
GmM