Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

Androidで日付時刻を簡単に扱えるThreeTenABPの話

こんにちは。初めまして。Androidエンジニアの斎藤です。 今回はJavaで日付/時刻などを扱うライブラリThreeTenをAndroidで利用するための基本的な導入方法、使用方法について紹介します。

ThreeTenABPって何?

Java8から導入されたDate and Time API(JSR-310)を参照実装したものをAndroidで利用可能なようにバックポートしたものです。 ABPはAndroid Backportの略です。バックポート人はJake Wharton大先生です。

導入方法

AndroidStudioのbuild.gradleに下記を追加します。

compile 'com.jakewharton.threetenabp:threetenabp:1.0.3'

Applicationを継承したクラスのonCreate()メソッドで初期化します。

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

AndroidManifestにも忘れずに。

<application
    android:name=".MyApplication" <-
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

簡単な使用方法

LocalDate

LocalDateは日付に関する情報を扱うクラスです。

// 今日の日付を取得する
LocalDate todayDate = LocalDate.now();
Log.d(TAG, "todayDate: " + todayDate); // -> todayDate: 2016-06-24

// 今日の日付の年(Year)を取得する
int year = todayDate.getYear();
Log.d(TAG, "todayDate: year " + year); // -> todayDate: year 2016
// 今日の日付の月(Month)を取得する
int monthValue = todayDate.getMonthValue();
Log.d(TAG, "todayDate: monthValue " + monthValue); // -> todayDate: monthValue 6
// 今日の日付の日(Day)を取得する
int dayOfMonth = todayDate.getDayOfMonth();
Log.d(TAG, "todayDate: dayOfMonth " + dayOfMonth); // -> todayDate: dayOfMonth 24
// 今日の日付の週(Week)を取得する
String dayOfWeek = todayDate.getDayOfWeek().toString();
Log.d(TAG, "todayDate: dayOfWeek " + dayOfWeek); // -> todayDate: dayOfWeek FRIDAY

フォーマットも簡単。

// 表示を切り替えてみる
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
String formatted = todayDate.format(formatter);
Log.d(TAG, "formatted: " + formatted); // -> formatted: 2016年06月24日

その他、日付の演算も直感的で簡単にできます。

// 1年前の日付を取得する
LocalDate oneYearAgo = todayDate.minusYears(1L);
Log.d(TAG, "oneYearAgo: " + oneYearAgo); // -> oneYearAgo: 2015-06-24
// 1年後の日付を取得する
LocalDate oneYearLater = todayDate.plusYears(1L);
Log.d(TAG, "oneYearLater: " + oneYearLater); // -> oneYearLater: 2017-06-24

// 1か月前の日付を取得する
LocalDate oneMonthAgo = todayDate.minusMonths(1L);
Log.d(TAG, "oneMonthAgo: " + oneMonthAgo); // -> oneMonthAgo: 2016-05-24
// 1か月後の日付を取得する
LocalDate oneMonthLater = todayDate.plusMonths(1L);
Log.d(TAG, "oneMonthLater: " + oneMonthLater); // -> oneMonthLater: 2016-07-24

// 1週間前の日付を取得する
LocalDate oneWeekAgo = todayDate.minusWeeks(1L);
Log.d(TAG, "oneWeekAgo: " + oneWeekAgo); // -> oneWeekAgo: 2016-06-17
// 1週間後の日付を取得する
LocalDate oneWeekLater = todayDate.plusWeeks(1L);
Log.d(TAG, "oneWeekLater: " + oneWeekLater); // -> oneWeekLater: 2016-07-01

// 1日前の日付を取得する
LocalDate oneDayAgo = todayDate.minusDays(1L);
Log.d(TAG, "oneDayAgo: " + oneDayAgo); // -> oneDayAgo: 2016-06-23
// 1日後の日付を取得する
LocalDate oneDayLater = todayDate.plusDays(1L);
Log.d(TAG, "oneDayLater: " + oneDayLater); // -> oneDayLater: 2016-06-25

LocalTime

LocalTimeは時刻に関する情報を扱うクラスです。

// 現在の時刻を取得する
LocalTime localTime = LocalTime.now();
Log.d(TAG, "localTime: " + localTime); // -> localTime: 17:44:21.557

// 現在の時刻から時(Hour)を取得する
int hour = localTime.getHour();
Log.d(TAG, "localTime: hour " + hour); // -> localTime: hour 17
// 現在の時刻から分(Minutes)を取得する
int minute = localTime.getMinute();
Log.d(TAG, "localTime: minute " + minute); // -> localTime: minute 44
// 現在の時刻から秒(Second)を取得する
int second = localTime.getSecond();
Log.d(TAG, "localTime: second " + second); // -> localTime: second 21
// 現在の時刻からナノ秒(Nano)を取得する
int nano = localTime.getNano();
Log.d(TAG, "localTime: nano " + nano); // -> localTime: nano 557000000

フォーマットも。

// 表示を切り替える
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH時mm分ss.SSS秒");
String formatted = localTime.format(formatter);
Log.d(TAG, "formatted: " + formatted); // -> formatted: 17時44分21.557秒

演算も。

// 1時間前の時刻を取得する
LocalTime oneHourAgo = localTime.minusHours(1L);
Log.d(TAG, "oneHourAgo: " + oneHourAgo);
// 1時間前の時刻を取得する
LocalTime oneHourLater = localTime.plusHours(1L);
Log.d(TAG, "oneHourLater: " + oneHourLater);

// 1分前の時刻を取得する
LocalTime oneMinutesAgo = localTime.minusMinutes(1L);
Log.d(TAG, "oneMinutesAgo: " + oneMinutesAgo);
// 1分後の時刻を取得する
LocalTime oneMinutesLater = localTime.plusMinutes(1L);
Log.d(TAG, "oneMinutesLater: " + oneMinutesLater);

// 1秒前の時刻を取得する
LocalTime oneSecondsAgo = localTime.minusSeconds(1L);
Log.d(TAG, "oneSecondsAgo: " + oneSecondsAgo);
// 1秒後の時刻を取得する
LocalTime oneSecondsLater = localTime.plusSeconds(1L);
Log.d(TAG, "oneSecondsLater: " + oneSecondsLater);

// 1ナノ秒後の時刻を取得する
LocalTime oneNanosAgo = localTime.minusNanos(1L);
Log.d(TAG, "oneNanosAgo: " + oneNanosAgo);
// 1ナノ後の時刻を取得する
LocalTime oneNanosLater = localTime.plusNanos(1L);
Log.d(TAG, "oneNanosLater: " + oneNanosLater);

LocalDateTime

LocalDateTimeは日付と時刻に関する情報を扱うクラスです。

// 現在の日付と時刻を取得する
LocalDateTime localDateTime = LocalDateTime.now();
Log.d(TAG, "localDateTime: " + localDateTime); // -> localDateTime: 2016-06-24T17:44:21.563

上記2つで紹介したメソッドももちろん利用可能です。 加えて日付と時刻両方に関する演算も可能です。

// 1年と1時間前の日付と時刻を取得する
LocalDateTime oneYearAndHourAgo = localDateTime.minusYears(1L).minusHours(1L);
Log.d(TAG, "oneYearAndHourAgo: " + oneYearAndHourAgo); // -> oneYearAndHourAgo: 2015-06-24T16:44:21.563
// 1年と1時間後の日付と時刻を取得する
LocalDateTime oneYearAndHourLater = localDateTime.plusYears(1L).plusHours(1L);
Log.d(TAG, "oneYearAndHourLater: " + oneYearAndHourLater); // -> oneYearAndHourLater: 2017-06-24T18:44:21.563

比較も簡単です。

// 指定した日時の差分を取得する
LocalDateTime from = LocalDateTime.of(2016, 6, 24, 16, 30, 30);
LocalDateTime to = LocalDateTime.now();
Duration duration = Duration.between(from, to);
long durationHours = duration.toHours();
Log.d(TAG, "durationHours: " + durationHours); // -> durationHours: 3

ZonedDateTime

ZonedDateTimeは日付と時刻に関する情報を扱うクラスです。 LocalDateTimeとの違いはタイムゾーンがつきます。

// 現在の日付と時刻を取得する
ZonedDateTime zonedDateTime = ZonedDateTime.now();
Log.d(TAG, "zonedDateTime: " + zonedDateTime); // -> zonedDateTime: 2016-06-24T17:44:21.565+09:00[Asia/Tokyo]

おわりに

今回は簡単な使い方のみの紹介でしたが従来のDate, Calenderに比べてだいぶ使いやすくなったなぁという印象です。 積極的に利用してきたいと思いました。また、本記事を書くにあたり参考にした記事を後術しますが、中でも参考になったのが下記です。 http://builder.japan.zdnet.com/sp_oracle/weblogic/35067620/ なぜ、JSR-310が必要になったかから始まり、次の給料日を求めるなど実用的(?)なサンプルもあり為になりました。ぜひ読んでみてください。

今回作成したサンプルプロジェクトはGithubリポジトリへあげてあります。

参考にしたもの

[ThreeTenABP]

https://github.com/JakeWharton/ThreeTenABP

[日本人のためのDate and Time API Tips]

http://www.coppermine.jp/docs/programming/2013/12/jsr310-tips.html

[JavaDoc]

http://docs.oracle.com/javase/8/docs/api/

[必修! Date and Time API──Java SE 8の新日時APIの基本を学ぶ]

http://builder.japan.zdnet.com/sp_oracle/weblogic/35067620/

[今日から始めるJava8]

http://acro-engineer.hatenablog.com/entries/2013/02/06

[Androidで使える日付処理系のライブラリーを試してみた]

http://qiita.com/futabooo/items/206b71ee8022ac685ece

[日付操作(JSR-310 Date and Time API)]

http://terasolunaorg.github.io/guideline/5.1.0.RELEASE/ja/ArchitectureInDetail/Utilities/DateAndTime.html#overview

[旧日時APIとの相互変換&Java 6/7でDate-Time APIが使えるライブラリThreeTen Backport (1/3)]

http://www.atmarkit.co.jp/ait/articles/1504/02/news144.html

[Java 8日時APIの主なメソッドとフォーマット用のパターン文字の使い方 (1/6)]

http://www.atmarkit.co.jp/ait/articles/1501/29/news016.html


子育て家族アプリFammカップル専用アプリPairyを運営する Timers inc. では、現在エンジニアを積極採用中!急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP : http://timers-inc.com/engineerings

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる