はじめに
SNSアプリで使われるメッセージ送信時間の表示を実装したかったので、今回の記事を作成しました。
タイムスタンプとは
ある時刻にその電子データが存在していたことと、それ以降改ざんされていないことを証明する技術。単位は1/1000(0.001秒)
日付の比較
1.TimeStampをZonedDatetimeに変換する
static ZonedDateTime ofInstant(Instant instant, ZoneId zone)
InstantからZonedDateTimeのインスタンスを取得する。
java.time.Instant
public final class Instant
1970年1月1日午前0時0分0秒(UTC)からの経過秒数をナノ秒で扱うクラス。
(ナノ秒 = 1億分の一秒)
static Instant ofEpochMilli(long epochMilli)
Instantのインスタンスをエポック1970-01-01T00:00:00Zからのミリ秒数を使用して取得する。
ZoneIdは、InstantおよびLocalDateTimeの間の変換に使用するルールを識別するために使用される。
fun getZonedDateTime(millis: Long): ZonedDateTime {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
}
2.エポックタイムを0時0分形式に切り捨てる
fun startTimeOfDay(millis: Long): Long {
val zonedEpochMillis = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault())
return zonedEpochMillis.truncatedTo(ChronoUnit.DAYS).toInstant().toEpochMilli()
}
public ZonedDateTime truncatedTo(TemporalUnit unit)
時間が切り捨てられた、ZonedDateTimeのコピーを返す。
引数には切り捨てる単位をTemporalUnitで指定する。
ここではTemporalUnitを実装した列挙型ChronoUnitの列挙定数DAYSを使用して日付単位で切り捨てる。
3.週の始まりの日付を取得する
fun startDayOfWeek(zonedDateTime: ZonedDateTime, dayOfWeek: DayOfWeek): ZonedDateTime {
return zonedDateTime.with(TemporalAdjusters.previousOrSame(dayOfWeek))
public ZonedDateTime with(TemporalAdjuster adjuster)
日時の調整済のコピーを返す。
previous(DayOfWeek dayOfWeek)
例えば、DayOfWeekでMONDAYを指定すると、1つ前の月曜日の時間オブジェクトが取得できる。
調整対象の日付より前で指定された曜日が最初に出現する日に日付を調整する(ただし、日付がすでにその曜日だった場合は同じオブジェクトが返される)。
4.比較
//同じ年であるか?
fun isSameYear(millis1: Long, millis2: Long): Boolean {
val year1 = getZonedDateTime(millis1).year
val year2 = getZonedDateTime(millis2).year
return year1 == year2
}
//同じ週であるか?
fun isSameWeek(millis1: Long, millis2: Long): Boolean {
val startDay1 = startDayOfWeek(getZonedDateTime(startTimeOfDay(millis1)), DayOfWeek.MONDAY)
val startDay2 = startDayOfWeek(getZonedDateTime(startTimeOfDay(millis2)), DayOfWeek.MONDAY)
return startDay1.compareTo(startDay2) == 0
}
//同じ日付であるか?
fun isSameDay(millis1: Long, millis2: Long): Boolean {
val day1 = getZonedDateTime(startTimeOfDay(millis1))
val day2 = getZonedDateTime(startTimeOfDay(millis2))
return day1.compareTo(day2) == 0
}
//昨日であるか?
fun isYesterday(millis: Long): Boolean {
val day = getZonedDateTime(startTimeOfDay(millis))
val yesterday = getZonedDateTime(startTimeOfDay(System.currentTimeMillis())).minusDays(1)
return day.compareTo(yesterday) == 0
}
まとめ
比較結果により、「23:00」、「昨日」、「日曜日」、「23/1/21」などフォーマットを変更すれば、よりユーザーにわかりやすいアプリになります。
メッセージの送信時間をエポックタイムで取得して、豊富に用意されているJavaの日付系APIを使って、柔軟に日付のフォーマットを変更することができました。