【Kotlin/Android Studio】現在の日付を取得する方法!DateTimeFormatterの使い方
この記事からわかること
- Android Studio/Kotlinで現在の日付情報を取得する方法
- DateTimeFormatterの使い方
- yyyy/mm/dd形式の種類
- 日付→文字列、文字列→日付(Date型)への変換
- 日本時間や元号を取得するには?
- Calendarクラスの使い方
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
現在の日付を取得する方法
Kotlinでは現在の日付や時間を取得するクラスがいくつか定義されています。それぞれに役割は異なりますがnowメソッドから取得できる点は変わりません。
- Date:java.util.DateクラスをKotlinでラップした特定のタイムゾーンに依存しない絶対時間
- LocalDate:ISO-8601暦法の日付情報
- LocalDateTime:ISO-8601暦法の日付と時間情報
- JapaneseDate:日本の暦法の日付情報
- ZonedDateTime:指定したゾーンの日付と時間情報
val date = Date()
import java.time.LocalDate
import java.time.chrono.JapaneseDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
val date = Date()
val local = LocalDate.now()
val localTime = LocalDateTime.now()
val japan = JapaneseDate.now()
val zone = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"))
println(date) // Sat Feb 17 00:41:41 UTC 2024
println(local) // 2024-02-17
println(localTime) // 2024-02-17T00:41:41.172648120
println(japan) // Japanese Reiwa 6-02-17
println(zone) // 2024-02-17T09:41:41.193866743+09:00[Asia/Tokyo]
LocalDateTimeで9時間のズレが生じる原因
LocalDateTimeクラスで時間まで取得した場合printした時刻(9時でした)とオブジェクトの時刻では0時とAM 9時で日時情報には誤差が生まれています。これはUTC(協定世界時)で日時情報を保持しているためであり、UTCと日本標準時(JTC)とは9時間ズレているため誤差が生まれてしまうのです。
文字列として出力するフォーマットを指定
先ほどはデフォルトの形式のまま出力されていましたが、DateTimeFormatterクラスを使用することで任意の形式の文字列に変更することができます。フォーマットパターンはofPatternの引数に文字列で渡します。
val now = LocalDateTime.now()
val df = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")
val fdate = df.format(now)
print(fdate) // 2023/07/24 10:40:52
表示されている日付情報が/区切りに変更になったことを確認できました。間の区切り文字に指定はないので日本語の年月日を指定することも可能です。
val now = LocalDateTime.now()
val df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒")
val fdate = df.format(now)
print(fdate) // 2023年07月24日 11時04分39秒
日本時間で取得する
val now = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"))
val df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒")
val fdate = df.format(now)
print(fdate) // 2023年07月24日 20時07分32秒
フォーマットパターンの種類
yyyy/MM/ddなどのフォーマットはあらかじめ指定されたシンボルを使用します。以下に公式サイトに載っていたものを抜粋したので参考にしてください。
| Symbol | 意味 | Examples |
|---|---|---|
| G | 元号 | 西暦; Anno Domini; A |
| u | 年 | 2004; 04 |
| y | 元号の年 | 2004; 04 |
| D | 年内通算日 | 189 |
| M/L | 年内月 | 7; 07; 7月; 7月; J |
| d | 月内通算日 | 10 |
| g | 修正ユリウス日 | 2451334 |
| Q/q | 四半期 | 3; 03; 第3四半期; 3rd quarter |
| Y | 週ベースの年 | 1996; 96 |
| w | 週ベースの年内週 | 27 |
| W | 月内週 | 4 |
| E | 曜日 | 火; 火曜日; 火 |
| e/c | ローカライズされた曜日 | 2; 02; 火; 火曜日; 火 |
| F | 月内曜日番号 | 3 |
| a | 午前/午後 | 午後 |
| h | 午前/午後の時 (1-12) | 12 |
| K | 午前/午後の時 (0-11) | 0 |
| k | 1日の時 (1-24) | 24 |
| H | 1日の時 (0-23) | 0 |
| m | 分 | 30 |
| s | 秒 | 55 |
| S | 秒以下の小数部分 | 978 |
| A | 1日のミリ秒 | 1234 |
| n | 秒以下のナノ秒 | 987654321 |
| N | 1日のナノ秒 | 1234000000 |
参考文献:公式:DateTimeFormatter
文字列からDate型への変換
「日付→文字列」ではなく「文字列→日付」へ変換したい場合はLocalDateのparseメソッドを使用します。引数には変換対象の文字列とそのフォーマットにあったDateTimeFormatterを渡します。
val formatter = DateTimeFormatter.ofPattern("yyyy年M月d日")
val dateStr = "2023年10月23日"
val day = LocalDate.parse(dateStr, formatter)
print(day) // 2023-10-23
print(day::class) // class java.time.LocalDate (Kotlin reflection is not available)
DateTimeFormatterのparseメソッドでも変換はできるようですがデータ型がParsedになるようです。
val formatter = DateTimeFormatter.ofPattern("yyyy年M月d日")
val dateStr = "2023年10月23日"
val day = formatter.parse(dateStr)
print(day) // {},ISO resolved to 2023-10-23
print(day::class) // class java.time.format.Parsed (Kotlin reflection is not available)
文字列から時間込みのDate型への変換
時間も含めてパースしたい場合はLocalDateTimeを使用します。
val formatter = DateTimeFormatter.ofPattern("yyyy年M月d日 HH時mm分ss秒")
val dateStr = "2023年10月23日 10時20分30秒"
val day = LocalDateTime.parse(dateStr, formatter)
print(day) // 2023-10-23T10:20:30
SimpleDateFormatでも日付の変換が可能
元号を取得する
元号を取得したい場合はJapaneseDateで取得したオブジェクトのeraプロパティから取得することが可能です。そのままではローマ字なのでgetDisplayNameメソッドの引数に表示するスタイルとロケールを指定すれば日本語で表示させることも可能です。
val japan = JapaneseDate.now()
val era = japan.era
print(era) // Reiwa
print(era.getDisplayName(TextStyle.FULL, Locale.JAPAN)) // 令和
スタイルは以下の通りですがFULLとSHORTは日本の場合同じなのでFULLだけ使用すれば良さそうです。
| 定数 | 出力例 |
|---|---|
FULL |
令和 |
FULL_STANDALONE |
令和 |
NARROW |
R |
NARROW_STANDALONE |
R |
SHORT |
令和 |
SHORT_STANDALONE |
令和 |
元号n年形式で取得する
元号のみではなく「元号n年」形式で取得したい場合のが多いと思います。これはDateTimeFormatterを使用してGy年と指定することで取得することができます。
val df = DateTimeFormatter.ofPattern("Gy年", Locale.JAPAN)
val jpEra = df.format(JapaneseDate.now())
print(jpEra) // 令和5年
西暦になってしまう場合
和暦で表示させたい場合はJapaneseDateオブジェクトに変換させる必要があります。これをしないと西暦で表示されてしまうので以下のように文字列から和暦のみを抽出したい場合は変換を繰り返して実装することになります。
val date = "1999年12月1日"
val formatter = DateTimeFormatter.ofPattern("yyyy年M月d日", Locale.JAPAN)
val birthday = LocalDate.parse(date, formatter)
val japanDay = JapaneseDate.from(birthday)
val df = DateTimeFormatter.ofPattern("Gy年", Locale.JAPAN)
val jpEra = df.format(japanDay)
print(jpEra) // 平成11年
日付を引き算/足し算して⚪︎日前/後を取得する
日付を引き算/足し算して⚪︎日前/後を取得するにはminusDaysメソッドまたはplusDaysメソッドを使用します。
val now = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"))
val oneDayBefore = now.minusDays(1)
val oneDayAfter = now.plusDays(1)
print(now) // 2023-10-28T23:43:12.217434296+09:00[Asia/Tokyo]
print(oneDayBefore) // 2023-10-27T23:43:12.217434296+09:00[Asia/Tokyo]
print(oneDayAfter) // 2023-10-29T23:43:12.217434296+09:00[Asia/Tokyo]
Calendarクラスから日時を1つずつ取得する
Calendarクラスを使用することで日時情報を1つ1つ取得することが可能です。ですが月のみ1ヶ月少ない数値が返ってくるので+1することで実際の月に合わせます。これは1月=0、2月=1という感じになっているからのようです。
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
val hour = c.get(Calendar.HOUR_OF_DAY)
val minute = c.get(Calendar.MINUTE)
val second = c.get(Calendar.SECOND)
print(year) // 2023
print(month + 1 ) // 8
print(day) // 3
print(hour) // 12
print(minute) // 32
print(second) // 17
UNIX形式のタイムスタンプを取得する
timeプロパティから自身の日付と1970年1月1日の00:00:00 UTCとの間隔(UNIX)をLong型のミリ秒数で取得できます。ミリ秒数なので秒単位で取得したい場合は1000でわる必要があります。
val date = Date()
val unixTimeMilliSeconds: Long = date.time // 1710855741810
val unixTimeSeconds: Long = unixTimeMilliSeconds / 1000 // 1710855741
UNIX形式のタイムスタンプをDate型に戻す
UNIX形式のタイムスタンプ値はDate型に簡単に戻すことが可能です。この際にちゃんとミリ秒単位でLong型のタイムスタンプでないと正しく変換できないので注意してください。
var date = Date(unixTimeMilliSeconds)
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。






