Как использовать ThreeTenABP в Android Project
Я добавляю этот вопрос, потому что я новичок в Java и Android, и я искал часы, пытаясь понять это. Ответ был получен из комбинации связанных ответов, поэтому я решил, что задокументирую то, что я узнал, для всех, кто может бороться. Смотри ответ.
Для некоторого фона, мой опыт в основном веб-разработки на PHP и немного Ruby. Моя единственная ОС - Linux (Ubuntu Studio), и я (неохотно) разрабатываю свое первое приложение для Android в Android Studio 2.1.2. Моя настройка Java следующая:
>java -version
> openjdk version "1.8.0_91"
> OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~15.10.1-b14)
> OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
2 ответа
Первое открытие: почему вы должны использовать ThreeTenABP вместо java.time, ThreeTen-Backport или даже Joda-Time
Это действительно короткая версия ОЧЕНЬ ДОЛГОГО ПРОЦЕССА определения нового стандарта. Все эти пакеты - одно и то же: библиотеки, которые предоставляют хорошую, современную функциональность обработки времени для Java. Различия тонкие, но важные.
Наиболее очевидным решением будет использование встроенного java.time
пакет, так как это новый стандартный способ работы со временем и датами в Java. Это реализация JSR 310, которая была новым стандартным предложением для обработки времени, основанным на библиотеке Joda-Time.
Тем не мение, java.time
был введен в Java 8. Android до Marshmallow работает на Java 7 ("Android N" - первая версия, представившая языковые функции Java 8). Таким образом, если вы не ориентируетесь только на Android N Nougat и выше, вы не можете полагаться на функции языка Java 8 (на самом деле я не уверен, что это на 100% верно, но я так понимаю). Так java.time
снаружи.
Следующим вариантом может быть Joda-Time, поскольку JSR 310 был основан на Joda-Time. Однако, как показывает readme ThreeTenABP, по ряду причин Joda-Time - не лучший вариант.
Следующим является ThreeTen-Backport, который поддерживает большую часть (но не все) Java 8 java.time
функциональность Java 7. Это хорошо для большинства случаев использования, но, как указано в readme ThreeTenABP, у него есть проблемы с производительностью с Android.
Таким образом, последний и, казалось бы, правильный вариант - ThreeTenABP.
Второе открытие: инструменты сборки и управление зависимостями
Поскольку компиляция программы, особенно той, которая использует кучу внешних библиотек, является сложной, Java почти всегда использует "инструмент сборки" для управления процессом. Make, Apache Ant, Apache Maven и Gradle являются инструментами сборки, которые используются с Java-программами (см. Этот пост для сравнения). Как отмечалось ниже, Gradle - это выбранный инструмент для сборки проектов Android.
Эти инструменты сборки включают управление зависимостями. Похоже, что Apache Maven первым включил централизованное хранилище пакетов. Maven представил Центральный репозиторий Maven, который обеспечивает функциональность, эквивалентную PHP composer
с Packagist и Ruby's gem
с rubygems.org. Другими словами, центральный репозиторий Maven для Maven (и Gradle) - то же, что Packagist для композитора - окончательный и безопасный источник для версионных пакетов.
Третье открытие: Gradle обрабатывает зависимости в проектах Android
Главное в моем списке дел - прочитать здесь документы Gradle, включая их бесплатные электронные книги. Если бы я читал эти недели назад, когда начал изучать Android, я бы наверняка знал, что Gradle может использовать центральный репозиторий Maven для управления зависимостями в проектах Android. Кроме того, как подробно описано в этом ответе Stackru, начиная с Android Studio 0.8.9, Gradle неявно использует Maven Central Repository через JCenter Bintray, что означает, что вам не нужно делать никаких дополнительных настроек для настройки репозитория - вы просто перечислите зависимостей.
Четвертое открытие: зависимости проекта перечислены в [project dir]/app/build.gradle
Опять же, очевидно для тех, кто имеет опыт использования Gradle в Java, но мне потребовалось некоторое время, чтобы понять это. Если вы видите, что люди говорят: "О, просто добавьте compile 'this-or-that.jar'
"или что-то подобное, знаю, что compile
директива в этом файле build.gradle, которая указывает зависимости времени компиляции. Вот официальная страница Gradle по управлению зависимостями.
Пятое открытие: ThreeTenABP управляется Джейком Уортоном, а не ThreeTen
Еще одна проблема, которую я потратил слишком много времени на выяснение. Если вы ищете ThreeTen в Maven Central, вы увидите только пакеты для threetenbp
не threetenabp
, Если вы пойдете в репозиторий GitHub для ThreeTenABP, вы увидите, что печально compile 'this-or-that'
под разделом загрузки файла Readme.
Когда я впервые запустил этот репозиторий github, я не знал, что означает эта строка компиляции, и я попытался запустить ее в своем терминале (с очевидным и предсказуемым сбоем). Разочарованный, я вернулся к нему лишь вскоре после того, как выяснил все остальное, и, наконец, понял, что это линия Maven Repo, указывающая на com.jakewharton.threetenabp
РЕПО, в отличие от org.threeten
Сделки РЕПО. Вот почему я думал, что пакета ThreeTenABP нет в репозитории Maven.
Резюме: заставить его работать
Теперь все это кажется довольно простым. Вы можете получить современные функции обработки времени в проекте Android, убедившись, что ваш [project folder]/app/build.gradle
файл имеет compile 'com.jakewharton.threetenabp:threetenabp:1.0.3'
линия в его dependencies
раздел:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "me.ahuman.myapp"
minSdkVersion 11
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:23.4.0'
implementation 'com.android.support:design:23.4.0'
implementation 'com.jakewharton.threetenabp:threetenabp:1.0.3'
}
Принятый ответ Каэля верен. Кроме того, я упомяну пару вещей и представлю схему получения функциональности java.time.
java.time встроен в Android 26+
Если нацелена на Android 26 или более позднюю версию, вы найдете реализацию JSR 310 (классы java.time) в комплекте с Android. Не нужно добавлять ThreeTenABP.
API почти идентичны
Чтобы уточнить, ThreeTenABP для Android - это адаптация библиотеки ThreeTen-Backport, которая обеспечивает большую часть функциональности java.time для Java 6 и Java 7. Этот задний порт имеет почти идентичный API с java.time.
Предположим, вы теперь ориентируетесь на Android до 26, поэтому вы используете ThreeTenABP. Позже вы можете в конечном итоге отказаться от поддержки этих более ранних версий Android, чтобы использовать классы java.time в комплекте с Android. Когда это произойдет, вам нужно внести несколько изменений в кодовую базу, кроме (а) переключенияimport
заявления, и (б) изменение любых звонков, которые вы сделали org.threeten.bp.DateTimeUtils
использовать новые методы преобразования, которые были добавлены в старые устаревшие классы даты и времени (Date
, GregorianCalendar
).
Процесс перехода от ThreeTenABP к java.time должен быть плавным и почти безболезненным.
Когда какой фреймворк использовать
Вот диаграмма, показывающая три фреймворка и указывающая, когда использовать какую из них в каких сценариях.
• Обновление: подключаемый модуль Android Gradle 4.0.0+ предлагает новую четвертую опцию, API-интерфейс, освобождающий от сахара, чтобы сделать доступным подмножество функций java.time, изначально не встроенных в более ранние версии Android. См. Верхнюю часть основного ответа Каэля.
О java.time
Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытесняют старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
To learn more, see the Oracle Tutorial. And search stackru for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
- JavaSE 8, JavaSE 9, JavaSE 10, JavaSE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- JavaSE 6 and JavaSE 7
- Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
Добавьте следующее в свой файл сборки gradle в Android Studio.
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
Создайте класс Application и инициализируйте его так:
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
Это решение охватывает все ThreeTenABP от установки до использования.
Android-проект Open Event помогает организаторам мероприятия организовать мероприятие и создать приложения (формат apk) для своих событий / конференций, предоставляя конечную точку API или zip-файл, созданный с использованием сервера Open Event. Для любого Event App очень важно, чтобы оно правильно обрабатывало часовой пояс. В Android-приложении Open Event есть возможность изменить настройки часового пояса. Пользователь может просматривать дату и время события и сеансов в часовом поясе события и местного часового пояса в приложении. ThreeTenABP предоставляет бэкпорт классов даты и времени Java SE 8 для Java SE 6 и 7. В этом блоге я объясняю, как использовать ThreeTenABP для обработки часовых поясов в Android.
1. Добавить зависимость
Чтобы использовать ThreeTenABP в вашем приложении, вы должны добавить зависимость в файл build.gradle вашего модуля приложения.
dependencies {
compile 'com.jakewharton.threetenabp:threetenabp:1.0.5'
testCompile 'org.threeten:threetenbp:1.3.6'
}
2. Инициализируйте ThreeTenABP
Теперь в методе onCreate() класса Application инициализируйте ThreeTenABP.
AndroidThreeTen.init(this);
3. Создайте метод getZoneId()
Сначала создайте метод getZoneId(), который будет возвращать ZoneId в соответствии с предпочтениями пользователя. Этот метод будет использоваться для форматирования и анализа дат. Здесь showLocal - предпочтение пользователя. Если showLocal имеет значение true, то эта функция вернет локальный идентификатор зоны по умолчанию, в противном случае - ZoneId события.
private static ZoneId geZoneId() {
if (showLocal || Utils.isEmpty(getEventTimeZone()))
return ZoneId.systemDefault();
else
return ZoneId.of(getEventTimeZone());
}
Здесь метод getEventTimeZone () возвращает строку часового пояса события.
ThreeTenABP имеет в основном два класса, представляющих дату и время.
- ZonedDateTime: '2011-12-03T10:15:30+01:00[Европа / Париж]'
- LocalDateTime: '2011-12-03T10: 15: 30'
ZonedDateTime содержит информацию о часовом поясе в конце. LocalDateTime не содержит часовой пояс.
4. Создать метод для разбора и форматирования
Теперь создайте getDate()
метод, который принимает isoDateString и возвращает объект ZonedDateTime.
public static ZonedDateTime getDate(@NonNull String isoDateString) {
return ZonedDateTime.parse(isoDateString).withZoneSameInstant(getZoneId());;
Создайте formatDate()
метод, который принимает два аргумента, первый - это строка формата, а второй - isoDateString. Этот метод вернет отформатированную строку.
public static String formatDate(@NonNull String format, @NonNull String isoDateString) {
return DateTimeFormatter.ofPattern(format).format(getDate(isoDateString));
}
5.Parsing:
String isoDateString = "2017-11-09T23: 08: 56 + 08: 00";
DateConverter.setEventTimeZone("Asia/Singapore");
DateConverter.setShowLocalTime(false);
ZonedDateTime dateInEventTimeZone = DateConverter.getDate(isoDateString);
dateInEventTimeZone.toString(); //2017-11-09T23:08:56+08:00[Asia/Singapore]
TimeZone.setDefault(TimeZone.getDefault());
DateConverter.setShowLocalTime(true);
ZonedDateTime dateInLocalTimeZone = DateConverter.getDate(dateInLocalTimeZone);
dateInLocalTimeZone.toString(); //2017-11-09T20:38:56+05:30[Asia/Kolkata]
Форматирование:
String date = "2017-03-17T14:00:00+08:00";
String formattedString = formatDate("dd MM YYYY hh:mm:ss a", date));
formattedString // "17 03 2017 02:00:00 PM"
Источник:
- Github репо: триТенаБП
- Учебник по форматированию DateTime от Jakob Jenkov
- Открытое мероприятие Android PR:
- Jodatime vs ThreeTenABP (Android инструмент сравнения даты / времени)
- Android Java конвертировать TimeZone с ThreeTenABP
- Блог Foss Assia