現在の日付と時刻を取得

投稿日:  更新日:

携帯端末は使用する場所(国・地域)と時刻を選びません。

ゆえに、何時何処で携帯端末を使用したとしても、アプリの画面に表示される日付と時刻の間違いは許されません。

これらの課題はプログラムで対応します。

プログラムで日付・時刻を正しく扱うには、「世界標準時(GMTとUTC)」や「タイムゾーン」といった概念や、専用に用意されたクラスの理解が必要です。

ここでは、プログラム中で現在の日付と時刻を取得する方法をまとめます。

スポンサーリンク

世界標準時(GMTとUTC)

世界標準時というと、GMT(グリニッジ標準時:Greenwich Mean Time)とUTC(協定世界時:Coordinated Universal Time)の2つが挙げられます。

どちらも、時刻(時分秒)の表現を定義したものです。両者の違いは表の通りです。

基準1秒の計測正確性
GMT
(UT0)
英国のグリニッジ天文台(経緯0度)で平均太陽が南中する時を正午
※グリニッジ子午線を太陽が通過する時
正午(昼の12時)から計測
地球の自転周期
(天文観測)
一定でない
(自転が一定でない)
GMT
(UT1)
地球の自転周期
+軸のズレを考慮
(天文観測)
GMT
(UT2)
地球の自転周期
+軸のズレを考慮
+季節変化を考慮
(天文観測)
UTCGMT(UT1)との差が±0.9秒以内
※「うるう秒」の加減算で補正
午前0時から計測
セシウム原子の振動数
(原子時計)
一定である
(超高精度)
※GMT:グリニッジ標準時(Greenwich Mean Time)
※UTC:協定世界時(Coordinated Universal Time)
※UT0,1,2:世界時の型

最初の標準時はGMTです。

GMTは「地球の自転周期(1日≒24時間)」から1秒の長さを計測しています。自転周期は天文観測により求めているため、天体の事象の影響を受けます。従って、年間を通して一定では無く、正確性に劣るという問題がありました。そこで、UT0,1,2(世界時の型)と改良が進められました。

GMTに代わり、現在の主流はUTCです。

UTCは「セシウム原子の振動数(9192631770[Hz])」から1秒の長さを計測しています。非常に正確です。正確であるがゆえに、GMTと差が発生してしまいます。そこで、うるう秒の加減算を行って、GMTと同じ時刻を示すように補正されます。

GMTとUTCは同じ時刻を示すことから、国際協定により「GMTとUTCは等しい」とされています。厳密には1秒未満の差があり、違うのですが…

スポンサーリンク

タイムゾーン(TimeZone)

朝に太陽は東から昇ります。場所を東に移動すると、東へ行くほど太陽は早い時刻に昇ります。朝をAM 6:00と定義した時、AM 6:00は「東に行くほど時間が進み、西に行くほど時間が遅れる」ことになります。

つまり、AM 6:00という時刻は場所によって異なります。

この事象をうまく表現するために、TimeZoneが設けられています。

タイムゾーン

1日は24時間です。地球を経度15°づつ24の区域(360°/24時間=15°)に分割して、各区域の時刻を「世界標準時の基準からの時差」という形で与えます。

例えば、UTC+0(またはGMT+0)はグリニッジ天文台(ロンドン)を含む区域の時刻です。また、日本はUTC+9となり、UTC+0から9時間進んだ時刻になります。

また、タイムゾーンを含めて日付と時刻を表現するときは、次のような書き方をします。

1900年1月1日0時0分0秒(UTC)        ... 時差 0の場所(ロンドン)の時刻
1900年1月1日0時0分0秒(UTC-5)      ... 時差-5の場所(ニューヨーク)の時刻
1900年1月1日0時0分0秒(UTC+9)      ... 時差+9の場所(東京)の時刻
1900年1月1日0時0分0秒(UTC+09:00)  ... 同上
1900年1月1日0時0分0秒(JST)        ... 同上(JST:Japan Standard Time)

実際のタイムゾーンの境界は直線ではありません。国内が同じ時刻になるように折れ曲がっています。その方が都合の良いためです。

スポンサーリンク

「時(とき)」を刻むカウンター

Androidシステム(UNIX系のOS)は、内部に「時(とき)」を刻むカウンターを持ちます。

このカウンターは、1970年1月1日0時0分0秒(UTC)を起点とした経過秒数をカウントしていて、カウント値から時刻が算出できます。実際のところ、1970年にAndroidシステムは存在していないので、カウントの起点は携帯端末へ時刻設定を行った時点(カウント値N)です。

カウンターのカウントはAndroidシステムが行いますが、原子時計のような正確性はありません。ですので、NTPサーバーと時刻同期を行わせるのが普通です。

POSIX Time

また、カウンターの精度はシステムに依存します。現在は、64bitの整数(long)のカウンターで、ナノ秒単位のカウントが大多数です。

このように、コンピュータシステムで時刻を表現する方法を「POSIX Time」と呼びます。

スポンサーリンク

現在時刻の取得 ~System.currentTimeMillis~

currentTimeMillis( )はPOSIX TimeのTimeカウンター値を直に読み出します。

読みだされる値は「1970年1月1日0時0分0秒(UTC)を起点とした経過秒数のカウント値」です。精度はミリ秒になります。

        val _currentTime : Long = System.currentTimeMillis()
        System.out.println("カレントタイム   : ${_currentTime} [ms]")
		
I/System.out: カレントタイム   : 1679985063704 [ms]

似た関数(メソッド)にuptimeMillis( )があります。こちらは、「Androidシステムが稼働してからの経過秒数のカウント値」です。精度はミリ秒になります。

        val _uptime : Long = SystemClock.uptimeMillis()
        System.out.println("アップタイム   : ${_uptime} [ms]")
		
I/System.out: アップタイム   : 546689 [ms]
スポンサーリンク

現在時刻の取得 ~java.util~

java.utilパッケージはJavaの創成時から存在しているライブラリです。日付(年月日)と時刻(時分秒)を表すクラスを含みます。

Date

Dateクラスは日付(年月日)と時刻(時分秒)を表すクラスです。

Date( )でインスタンスを作成すると、POSIX TimeのTimeカウンター値とデフォルトのタイムゾーンを保持したインスタンスが作られます。

Dateは不変(Immutable object)クラスなので、インスタンス生成時に保持した値を変更できません。

toString( )やgetHours( )の出力は、保持したTimeカウンター値を保持したタイムゾーンに合わせて変換した値です。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        val _date = Date()
		
        System.out.println("カレントタイム = ${_date.time}");
        System.out.println("Date = ${_date}");
        System.out.println("日時  = %4d/%02d/%02d %02d:%02d:%02d".format(
            _date.year + 1900,  // 非推奨
            _date.month + 1,    // 非推奨
            _date.date,         // 非推奨
            _date.hours,        // 非推奨
            _date.minutes,      // 非推奨
            _date.seconds)      // 非推奨
        )
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680144306231
I/System.out: --------
I/System.out: カレントタイム = 1680144306231
I/System.out: Date = Thu Mar 30 11:45:06 GMT+09:00 2023
I/System.out: 日時  = 2023/03/30 11:45:06
I/System.out: --------

サンプル実行時のタイムゾーンと時刻

別のタイムゾーンに合わせた日付と時刻が欲しければ、SimpleDateFormatなどを使って変換します。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")
		
		val _date = Date()

        val _fmt = SimpleDateFormat()
        _fmt.timeZone = TimeZone.getTimeZone("Asia/Tokyo")  // 東京
        System.out.println("Date = ${_fmt.format(_date)}")
        _fmt.timeZone = TimeZone.getTimeZone("EST")         // ニューヨーク
        System.out.println("Date = ${_fmt.format(_date)}")
        _fmt.timeZone = TimeZone.getTimeZone("Greenwich")   // ロンドン
        System.out.println("Date = ${_fmt.format(_date)}")
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680144306231
I/System.out: --------
I/System.out: Date = 2023/03/30 11:45	... 東京
I/System.out: Date = 2023/03/29 21:45	... ニューヨーク
I/System.out: Date = 2023/03/30 2:45	... ロンドン
I/System.out: --------

現在、Dateクラスは、メソッドの一部が非推奨です。今後、Java8で追加されたjava.timeパッケージに含まれるLocalDateクラス、LocalTimeクラスなどの利用が推奨されます。

デフォルトのタイムゾーンとは
デフォルトのタイムゾーンとは、携帯端末に設定されたタイムゾーンのことです。
※図はApi 26の場合

デフォルトのタイムゾーン

Calendar

Calendarクラスは日付(年月日)と時刻(時分秒)を表すクラスです。

Calendar.getInstance()でインスタンスを作成すると、POSIX TimeのTimeカウンター値とデフォルトのタイムゾーンを保持し、タイムゾーンの現在の日付・時刻を初期値にしたインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        val cal = Calendar.getInstance()

        System.out.println("カレントタイム   : ${cal.timeInMillis}")
        System.out.println("タイムゾーンID   : ${cal.timeZone.getID()}")
        System.out.println("タイムゾーンName : ${cal.timeZone.getDisplayName()}")
        System.out.println("日時 : %4d/%02d/%02d %02d:%02d:%02d".format(
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.SECOND)
        ))
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680151502714
I/System.out: --------
I/System.out: カレントタイム   : 1680151502714
I/System.out: タイムゾーンID   : Asia/Tokyo
I/System.out: タイムゾーンName : 日本標準時
I/System.out: 日時 : 2023/03/30 13:45:02
I/System.out: --------

サンプル実行時のタイムゾーンと時刻

また、作成したインスタンスに対してタイムゾーンを変更すれば、その区域の現在の日付・時刻が取得できます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        val cal = Calendar.getInstance()

        val tzn1 = TimeZone.getTimeZone("Asia/Tokyo")   // 東京
        cal.timeZone = tzn1
        System.out.println("カレントタイム   : ${cal.timeInMillis}")
        System.out.println("タイムゾーンID   : ${tzn1.getID()}")
        System.out.println("タイムゾーンName : ${tzn1.getDisplayName()}")
        System.out.println("日時 : %4d/%02d/%02d %02d:%02d:%02d".format(
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.SECOND)
        ))
        System.out.println("--------\n")

        val tzn2 = TimeZone.getTimeZone("EST")          // ニューヨーク
        cal.setTimeZone(tzn2)
        System.out.println("カレントタイム   : ${cal.timeInMillis}")
        System.out.println("タイムゾーンID   : ${tzn2.getID()}")
        System.out.println("タイムゾーンName : ${tzn2.getDisplayName()}")
        System.out.println("日時 : %4d/%02d/%02d %02d:%02d:%02d".format(
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.SECOND)
        ))
        System.out.println("--------\n")

        val tzn3 = TimeZone.getTimeZone("Greenwich")    // ロンドン
        cal.timeZone = tzn3
        System.out.println("カレントタイム   : ${cal.timeInMillis}")
        System.out.println("タイムゾーンID   : ${tzn3.getID()}")
        System.out.println("タイムゾーンName : ${tzn3.getDisplayName()}")
        System.out.println("日時 : %4d/%02d/%02d %02d:%02d:%02d".format(
            cal.get(Calendar.YEAR),
            cal.get(Calendar.MONTH) + 1,
            cal.get(Calendar.DAY_OF_MONTH),
            cal.get(Calendar.HOUR_OF_DAY),
            cal.get(Calendar.MINUTE),
            cal.get(Calendar.SECOND)
        ))
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680151502714
I/System.out: --------
I/System.out: カレントタイム   : 1680151502714		... 東京
I/System.out: タイムゾーンID   : Asia/Tokyo
I/System.out: タイムゾーンName : 日本標準時
I/System.out: 日時 : 2023/03/30 13:45:02
I/System.out: --------
I/System.out: カレントタイム   : 1680151502714		... ニューヨーク
I/System.out: タイムゾーンID   : EST
I/System.out: タイムゾーンName : GMT-05:00
I/System.out: 日時 : 2023/03/29 23:45:02
I/System.out: --------
I/System.out: カレントタイム   : 1680151502714		... ロンドン
I/System.out: タイムゾーンID   : Greenwich
I/System.out: タイムゾーンName : GMT+00:00
I/System.out: 日時 : 2023/03/30 04:45:02
I/System.out: --------
スポンサーリンク

現在時刻の取得 ~java.time(API≧26)~

java.timeパッケージはJava8での追加され、AndroidにおいてはAPI≧26より使用可能になりました。

表に示すような、日付(年月日)と時刻(時分秒)を表すクラスを含みます。

クラス保持する値付属する情報不変(Immutable)
LocalDateタイムゾーンの日付
LocalTimeタイムゾーンの時刻
LocalDateTimeタイムゾーンの日付・時刻
ZonedDateTimeタイムゾーンの日付・時刻タイムゾーン
※JAVA8で追加、AndroidにおいてはAPI≧26より使用可能

表のクラスは不変(Immutable object)クラスなので、インスタンス生成時に保持した値を変更できません。

ですので、保持する値の異なるインスタンスが必要な場合は、再生成を行わなければなりません。

LocaleDate

LocaleDateクラスは日付(年月日)を表すクラスです。

LocaleDate.now( )でインスタンスを作成すると、デフォルトのタイムゾーンの現在の日付を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _localDate = LocalDate.now()
            System.out.println("LocalDate  = ${_localDate}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680139005357
I/System.out: --------
I/System.out: LocalDate  = 2023-03-30
I/System.out: --------

サンプル実行時のタイムゾーンと時刻

LocalDate.now( )の引数にタイムゾーンを指定してインスタンスを作成すると、指定したタイムゾーンの現在の日付を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _localDate1 = LocalDate.now(ZoneId.of("Asia/Tokyo")) // 東京
            System.out.println("LocalDate1 = ${_localDate1}");
            val _localDate2 = LocalDate.now(ZoneId.of("EST"))        // ニューヨーク
            System.out.println("LocalDate2 = ${_localDate2}");
            val _localDate3 = LocalDate.now(ZoneId.of("Greenwich"))  // ロンドン
            System.out.println("LocalDate3 = ${_localDate3}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680139005357
I/System.out: --------
I/System.out: LocalDate1 = 2023-03-30		... 東京
I/System.out: LocalDate2 = 2023-03-29		... ニューヨーク
I/System.out: LocalDate3 = 2023-03-30		... ロンドン
I/System.out: --------

LocalTime

LocalTimeクラスは時刻(時分秒)を表すクラスです。

LocaleTime.now( )でインスタンスを作成すると、デフォルトのタイムゾーンの現在の時刻を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _localTime = LocalTime.now()
            System.out.println("LocalTime  = ${_localTime}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680139005357
I/System.out: --------
I/System.out: LocalTime  = 10:16:45.358
I/System.out: --------

サンプル実行時のタイムゾーンと時刻

LocalTime.now( )の引数にタイムゾーンを指定してインスタンスを作成すると、指定したタイムゾーンの現在の時刻を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _localTime1 = LocalTime.now(ZoneId.of("Asia/Tokyo")) // 東京
            System.out.println("LocalTime1 = ${_localTime1}");
            val _localTime2 = LocalTime.now(ZoneId.of("EST"))        // ニューヨーク
            System.out.println("LocalTime2 = ${_localTime2}");
            val _localTime3 = LocalTime.now(ZoneId.of("Greenwich"))  // ロンドン
            System.out.println("LocalTime3 = ${_localTime3}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680139005357
I/System.out: --------
I/System.out: LocalTime1 = 10:16:45.359		... 東京
I/System.out: LocalTime2 = 20:16:45.359		... ニューヨーク
I/System.out: LocalTime3 = 01:16:45.359		... ロンドン
I/System.out: --------

LocalDateTime

LocalDateTimeクラスは日付(年月日)と時刻(時分秒)を表すクラスです。

LocalDateTime.now( )でインスタンスを作成すると、デフォルトのタイムゾーンの現在の日付と時刻を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _localDateTime = LocalDateTime.now()
            System.out.println("LocalDateTime  = ${_localDateTime}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680141436709
I/System.out: --------
I/System.out: LocalDateTime  = 2023-03-30T10:57:16.710
I/System.out: --------

サンプル実行時のタイムゾーンと時刻

LocalDateTime.now( )の引数にタイムゾーンを指定してインスタンスを作成すると、指定したタイムゾーンの現在の日付と時刻を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _localDateTime1 = LocalDateTime.now(ZoneId.of("Asia/Tokyo")) // 東京
            System.out.println("LocalDateTime1 = ${_localDateTime1}");
            val _localDateTime2 = LocalDateTime.now(ZoneId.of("EST"))        // ニューヨーク
            System.out.println("LocalDateTime2 = ${_localDateTime2}");
            val _localDateTime3 = LocalDateTime.now(ZoneId.of("Greenwich"))  // ロンドン
            System.out.println("LocalDateTime3 = ${_localDateTime3}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680141436709
I/System.out: --------
I/System.out: LocalDateTime1 = 2023-03-30T10:57:16.710	... 東京
I/System.out: LocalDateTime2 = 2023-03-29T20:57:16.710	... ニューヨーク
I/System.out: LocalDateTime3 = 2023-03-30T01:57:16.710	... ロンドン
I/System.out: --------

ZonedDateTime

ZonedDateTimeクラスは日付(年月日)と時刻(時分秒)を表すクラスです。

LocalDateTimeクラスとの違いは、日付と時刻の保持とは別に、タイムゾーンの情報を持つことができる点です。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _zonedDateTime = ZonedDateTime.now()
            System.out.println("ZonedDateTime  = ${_zonedDateTime}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680141436709
I/System.out: --------
I/System.out: ZonedDateTime  = 2023-03-30T10:57:16.711+09:00[Asia/Tokyo]
I/System.out: --------

サンプル実行時のタイムゾーンと時刻

ZonedDateTime.now( )の引数にタイムゾーンを指定してインスタンスを作成すると、指定したタイムゾーンの現在の日付と時刻を保持したインスタンスが作られます。

        System.out.println("カレントタイム = ${System.currentTimeMillis()}")
        System.out.println("--------\n")

        if(Build.VERSION.SDK_INT >= 26) {
            val _zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo")) // 東京
            System.out.println("ZonedDateTime1 = ${_zonedDateTime1}");
            val _zonedDateTime2 = ZonedDateTime.now(ZoneId.of("EST"))        // ニューヨーク
            System.out.println("ZonedDateTime2 = ${_zonedDateTime2}");
            val _zonedDateTime3 = ZonedDateTime.now(ZoneId.of("Greenwich"))  // ロンドン
            System.out.println("ZonedDateTime3 = ${_zonedDateTime3}");
        }
        System.out.println("--------\n")
I/System.out: カレントタイム = 1680141436709
I/System.out: --------
I/System.out: ZonedDateTime1 = 2023-03-30T10:57:16.711+09:00[Asia/Tokyo]  ... 東京
I/System.out: ZonedDateTime2 = 2023-03-29T20:57:16.711-05:00[EST]         ... ニューヨーク
I/System.out: ZonedDateTime3 = 2023-03-30T01:57:16.711Z[Greenwich]        ... ロンドン
I/System.out: --------
スポンサーリンク

関連記事:

スケジュール管理やアラーム機能を実装するアプリのテストで、端末の時刻を自由に変更できたら便利です。なので、端末の時刻を変更するテストルールを作成してみました。 ...
スケジュール管理やアラーム機能を実装するアプリのテストで、端末の日付を自由に変更できたら便利です。なので、端末の日付を変更するテストルールを作成してみました。 ...
スポンサーリンク