JSR-310 で Date/Calendar を避けて通る

Android上で既存のフォーマットを利用して日時を表示しようとすると, android.text.format.DateUtils は利用したい.

「ThreeTenABP」で捨てれないのか android.text.format.DateUtils

JSR-310系の LocalDate などと Unixタイム間を自在に変換できない.

LocalDateTime系は時差情報を持たないので、時刻の起点が定まっていない(システム依存)という特徴があります。一方でInstantとjava.util.Dateは暗黙的にUTCという時差情報をもっており、時刻の起点が定まっています。これがLocalDateTime.toInstantなるメソッドがない理由です

Java8日付時刻APIの使いづらさと凄さ - きしだのはてな

「Local* は時刻の起点をもっていない」

ので, それを追加した ZonedDateTime/OffsetDateTime に一度変換して Instant を経由して Epoc へ, 逆も同じ要領で.


long epochSecondF = 1234567890;
long epochMilliF = epochSecondF * 1000L;

Instant instantF = Instant.ofEpochMilli(epochMilliF);
//Instant instantF = Instant.ofEpochSecond(epochSecond);

ZonedDateTime zonedDateTime = instantF.atZone(ZoneOffset.systemDefault());
//OffsetDateTime offsetDateTime = instantF
//    .atOffset(ZoneOffset.systemDefault().getRules().getOffset(Instant.EPOCH));

zonedDateTime = zonedDateTime
    .plusDays(123)
    .plusHours(123)
    .plusMinutes(123)
    .plusMonths(123)
    .plusWeeks(123)
    .minusDays(123)
    .with(TemporalAdjusters.lastDayOfMonth())
    .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));

//offsetDateTime = offsetDateTime
//    .plusDays(123);
//    .plusHours(123)
//    .plusMinutes(123)
//    .plusMonths(123)
//    .plusWeeks(123)
//    .minusDays(123)
//    .with(TemporalAdjusters.lastDayOfMonth())
//    .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));

Instant instantR = zonedDateTime.toInstant();
//Instant instantR = offsetDateTime.toInstant();

long epochMilliR = instantR.toEpochMilli();
//long epochSecondR = instantR.getEpochSecond();

のように, タイムゾーンやオフセットの情報は, Android端末の設定側から取得する.


ZoneOffset.systemDefault()


ZoneOffset.systemDefault().getRules().getOffset(Instant.EPOCH)

利用者の属するタイムゾーンを利用してカレンダー周りの計算をして, Epoch と行き来するなら,


  public static ZonedDateTime toZonedDateTime(long epochMilli) {
    return Instant.ofEpochMilli(epochMilli).atZone(ZoneId.systemDefault());
  }

  public static long toEpocMilli(ZonedDateTime zonedDateTime) {
    return zonedDateTime.toInstant().toEpochMilli();
  }

そして表示の前にフォーマットする.


String formatted = DateUtils.formatDateTime(context, toEpocMilli(zonedDateTime), 
       FORMAT_SHOW_YEAR | FORMAT_SHOW_DATE | FORMAT_SHOW_WEEKDAY | FORMAT_SHOW_TIME | FORMAT_ABBREV_ALL);

// 2016年12月14日(水) 10:13
// Wed, 14 Dec 2016 00:13
// Tue, Dec 13, 2016, 20:13
// 2016年12月14日週三 09:13
// 2016년 12월 14일 (수) 10:13
// ...

「ThreeTenABP」で捨てれないのか android.text.format.DateUtils