Kotlin / kotlinx-datetime

KotlinX multiplatform date/time library
Apache License 2.0
2.37k stars 97 forks source link

Precision loss for NSDate #427

Open wkornewald opened 2 weeks ago

wkornewald commented 2 weeks ago

When converting an Instant to NSDate and back to Instant the value is rounded to milliseconds. However, when testing I see microsecond precision after calling toNSDate() and even when using NSDate.addTimeInterval() and also when instantiating a new NSDate() object. This doesn’t match what the docstring claims.

You probably only refer to the NSDateFormatter having a bug and dropping to millisecond precision? The rest of the NSDate API seems to work fine with microsecond precision though, so it makes no sense to be lossy in Kotlin.

At the Kotlin level, the loss in precision only happens in the NSDate.toKotlinInstant() extension function. Could you please fix this function to preserve microsecond precision instead of millisecond precision - consistent with the test result?

Also, the toNSDate() function doesn't round the last (microsecond) digit, which is probably a bug.

dkhalanskyjb commented 2 weeks ago

Yes, when I call print(NSDate().timeIntervalSinceReferenceDate) in Swift, I do get microsecond precision. Sub-milliseconds do disappear only when I try printing NSDate directly. We should fix this.

Also, the toNSDate() function doesn't round the last (microsecond) digit

We delegate to NSDate.dateWithTimeIntervalSince1970 for this, so it's not our decision.

wkornewald commented 2 weeks ago

Also, the toNSDate() function doesn't round the last (microsecond) digit

We delegate to NSDate.dateWithTimeIntervalSince1970 for this, so it's not our decision.

We are responsible for passing a value with a certain precision expectation though. In order for the back and forth conversion to have no information loss beyond the precision we have to round.

wkornewald commented 1 week ago

Actually, while implementing a PR for this I've noticed in your stress test that due to Double precision limits we sometimes were around 20 microseconds off and often times around 1-2 microseconds. So, we could safely increase the precision at least 10x to 0.1ms, but maybe we should actually keep the current millisecond precision and close this ticket. There's little hope for NSDate. :(

dkhalanskyjb commented 6 days ago

In what date ranges did you observe the loss of precision? If it's only dates outside the range most useful in practice (±100 years from now), maybe it's still worth extending our precision limit.

wkornewald commented 6 days ago

It was quite large around 1000 years before/after 1970 (e.g. year 800 or 3300). I haven't checked if there's an acceptable range though.