Ошибка TripleTen-Backport на Android - ZoneRulesException: файлы данных временной зоны не зарегистрированы

Я использую библиотеку ThreeTen-Backport для моего Android-проекта (потому что java.time еще не реализован в разработке Android).

Когда я пишу LocalDate today=LocalDate.now(); или LocalTime time=LocalTime.now();, я получаю следующее исключение:

Caused by: org.threeten.bp.zone.ZoneRulesException: 
  No time-zone data files registered   
      at org.threeten.bp.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:176)
      at org.threeten.bp.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:133)
      at org.threeten.bp.ZoneRegion.ofId(ZoneRegion.java:143)
      at org.threeten.bp.ZoneId.of(ZoneId.java:357)
      at org.threeten.bp.ZoneId.of(ZoneId.java:285)
      at org.threeten.bp.ZoneId.systemDefault(ZoneId.java:244)
      at org.threeten.bp.Clock.systemDefaultZone(Clock.java:137)
      at org.threeten.bp.LocalDate.now(LocalDate.java:165)

Такая же строка кода хорошо работает в другом проекте java, который использует собственную библиотеку java.time.

Я искал возможное решение, но не нашел ничего полезного: одно решение предложило мне использовать другую банку, которая включает в себя правила часовых поясов, и другие предположили, что внутри пути к классам могут быть две или более библиотеки ThreeTenBP.
Эти случаи не соответствуют моему делу.

Внутри файла build.gradle в разделе зависимостей я пробовал несколько конфигураций:

  • Сначала я использовал - compile 'com.jakewharton.threetenabp:threetenabp:1.0.3'
  • Затем я попробовал - compile 'org.threeten:threetenbp:1.0.3'
  • После этого я попробовал - compile 'org.threeten:threetenbp:1.3.1'
  • В настоящее время я использую compile 'org.threeten:threetenbp:1.3.2'

Я не знаю, что не так с этой строкой кода и как ее исправить.
Методы LocalDate.now() и LocalTime.now() должны работать без указания часового пояса.

Ответы

Ответ 1

Для проекта Android вы должны использовать

implementation 'com.jakewharton.threetenabp:threetenabp:1.0.3'

Убедитесь, что вы вызываете AndroidThreeTen.init(this); перед использованием классов из библиотеки. Это будет читать данные часовых поясов (включены в библиотеку). Вы можете инициализировать библиотеку в своем классе Application в методе onCreate так же, как это рекомендуется в README.

Ответ 2

Вместо инициализации библиотеки вы можете попробовать это:

LocalDateEx.kt

object LocalDateEx {
    /**an alternative of LocalDate.now(), as it requires initialization using AndroidThreeTen.init(context), which takes a bit time (loads a file)*/
    @JvmStatic
    fun getNow(): LocalDate = Calendar.getInstance().toLocalDate()
}

fun Calendar.toLocalDate(): LocalDate = LocalDate.of(get(Calendar.YEAR), get(Calendar.MONTH) + 1, get(Calendar.DAY_OF_MONTH))

LocalTimeEx.kt

object LocalTimeEx {
    /**an alternative of LocalDateTime.now(), as it requires initialization using AndroidThreeTen.init(context), which takes a bit time (loads a file)*/
    @JvmStatic
    fun getNow(): LocalTime = Calendar.getInstance().toLocalTime()
}

fun Calendar.toLocalTime(): LocalTime = LocalTime.of(get(Calendar.HOUR_OF_DAY), get(Calendar.MINUTE), get(Calendar.SECOND), get(Calendar.MILLISECOND) * 1000000)

LocalDateTimeEx.kt

object LocalDateTimeEx {
    /**an alternative of LocalDateTime.now(), as it requires initialization using AndroidThreeTen.init(context), which takes a bit time (loads a file)*/
    @JvmStatic
    fun getNow(): LocalDateTime = Calendar.getInstance().toLocalDateTime()
}

private fun Calendar.toLocalDateTime(): LocalDateTime = LocalDateTime.of(get(Calendar.YEAR), get(Calendar.MONTH) + 1, get(Calendar.DAY_OF_MONTH), get(Calendar.HOUR_OF_DAY), get(Calendar.MINUTE), get(Calendar.SECOND),
        get(Calendar.MILLISECOND) * 1000000)

Использование:

   val today=LocalDateEx.getNow()
   val today2=LocalTimeEx.getNow()
   val today3=LocalDateTimeEx.getNow()