kotlinx-datetime icon indicating copy to clipboard operation
kotlinx-datetime copied to clipboard

Provide the means for a non-default timezone database

Open lwasyl opened this issue 2 years ago • 4 comments

When developing for Android, developers can use desugaring to enable java.time APIs that will be used for kotlinx-datetime implementation on JVM. However, Android doesn't allow developers to provide their own time zone database to be used with those APIs. On APIs 26-28 this means devices will only use time zones provided with the system update (so mostly outdated). On APIs 29+, time zone updates are provided via project mainline, which is supposed to happen regardless of OEM support. However, project mainline depends on Google Play Services infrastructure, which a lot of devices (like Huawei or custom ROMs) don't have. That prevents developers who want to use most recent TZ database from using java.time APIs, and right now that includes kotlinx-datetime.

For that reason, it'd be great to be able to use ThreeTenBP backend with kotlinx-datetime on JVM, ensuring that we can provide most recent time zone database with the app, instead of relying on OEMs or the devices having Google services installed.

See also:

  • https://source.android.com/devices/architecture/modular-system/timezone
  • https://issuetracker.google.com/issues/159421054
  • https://www.zacsweers.dev/ticktock-desugaring-timezones/

lwasyl avatar May 09 '22 15:05 lwasyl

Is it correct that the actual issue is only with using non-standard time zone database? If we manage to provide this functionality without 310bp, will the issue still be solved?

dkhalanskyjb avatar May 11 '22 10:05 dkhalanskyjb

Yes, any way to bundle the time zone database with the app and use it instead of the system tzdb (like 310bp does: https://github.com/ThreeTen/threetenbp/blob/master/src/main/resources/org/threeten/bp/TZDB.dat) would solve the issue. I suggested 310bp because according to https://issuetracker.google.com/issues/159421054#comment3 it's not possible on Android to set time zone data that would be used by java.time APIs

lwasyl avatar May 11 '22 11:05 lwasyl

There are some challenges that providing a possibility to use a custom time zone database will have us to face. For example, it could lead to the following effects:

  • two kotlinx time zone instances with the same ids can produce different results if one of them was loaded from the system tz provider and the other from a custom tzdb.
  • similar to the above, instant-date/time conversions using a kotlinx time zone from a custom tzdb may differ from the conversions performed with a java.time ZoneId with the same id or in other apps that use native API, e.g. you may see different time in the same time zone in your app and in the world times page of the standard clock app.
  • kotlinx time zone instance may be no longer convertible to a java.time ZoneId, if the former was loaded from a custom tzdb.

So I would be interested to discuss whether these effects can cause problems in practical aspect, and if they do, if there are ideas how to deal with them.

ilya-g avatar May 13 '22 21:05 ilya-g

Some 2c thoughts!

two kotlinx time zone instances with the same ids can produce different results if one of them was loaded from the system tz provider and the other from a custom tzdb.

similar to the above, instant-date/time conversions using a kotlinx time zone from a custom tzdb may differ from the conversions performed with a java.time ZoneId with the same id or in other apps that use native API, e.g. you may see different time in the same time zone in your app and in the world times page of the standard clock app.

I don't think this problem is new right? There's always a risk of, say, a server or API sending a zone ID that is newer than what the client understands if it is out of date. If anything I'd expect allowing custom loading to help with this because it would lend more agency to owners to bring their own newer data

kotlinx time zone instance may be no longer convertible to a java.time ZoneId, if the former was loaded from a custom tzdb.

Assuming the ID is still just a string ID under the hood, it would be simple enough to just convert over to the java.time.ZoneId right?

val zoneId = java.time.ZoneId.of(kotlinxTimeZone.id)

ZacSweers avatar May 14 '22 21:05 ZacSweers