Как использовать ThreeTenABP в Android-проекте

Я задаю этот вопрос, потому что я новичок в Java и 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)

Ответ 1

Первое открытие: почему вы должны использовать 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. Это хорошо для большинства случаев использования, но, как указано в Чтение ThreeTenABP, у него проблемы с производительностью Android.

Поэтому последний и, казалось бы, правильный вариант - ThreeTenABP.

Второе открытие: инструменты сборки и управление зависимостями

Поскольку компиляция программы, особенно с использованием нескольких внешних библиотек, является сложной, Java почти всегда использует "инструмент сборки" для управления процессом. Make, Apache Ant, Apache Maven и Gradle - все это инструменты сборки, которые используются с программами Java (см. это пост для сравнения). Как уже отмечалось ниже, Gradle - это выбранный инструмент для сборки проектов Android.

Эти инструменты сборки включают управление зависимостями. Похоже, что Apache Maven первым включил централизованное хранилище пакетов. Maven представил Центральный репозиторий Maven, который обеспечивает функциональность, эквивалентную php composer с Packagist и Ruby gem с rubygems.org. Другими словами, центральный репозиторий Maven для Maven (и Gradle) - то же самое, что Packagist для композитора - окончательный и безопасный источник для версионных пакетов.

Третье открытие: Gradle обрабатывает зависимости в проектах Android

Главное в моем списке дел - прочитать документы Gradle здесь, включая их бесплатные электронные книги. Если бы я читал эти недели назад, когда начал изучать Android, я бы наверняка знал, что Gradle может использовать центральный репозиторий Maven для управления зависимостями в проектах Android. Более того, как подробно описано в этом ответе Qaru, начиная с Android Studio 0.8.9, Gradle неявно использует центральный репозиторий Maven через Bintray JCenter, что означает, что вам не нужно делать никаких дополнительных настроек для настройки репо - вы просто перечислите зависимости.

Четвертое открытие: зависимости проекта перечислены в [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, указывающая на репо 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.2.1'
}

Также добавьте это в класс приложения:

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
        AndroidThreeTen.init(this);
        //...
    }
}

Ответ 2

Это решение охватывает все 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, то эта функция будет возвращать Default Local ZoneId, в противном случае 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"

Источник:

Ответ 3

Добавьте следующее в свой файл Gradle.

/* android back port for java time  */
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'

Создайте класс приложения и инициализируйте его.

public class App extends Application {    
    @Override
    public void onCreate() {
        super.onCreate();
       AndroidThreeTen.init(this);
    }
}