Javaで時間を取得する方法をお探しだろうか?
データベースにデータを登録した時間や更新した時間、プログラムの実行速度がどれくらいになるか処理時間を計測するなど、システムにおいて時間を扱うケースは多い。
Javaでは日付に関するクラスから時間を取得することが多いため、時間について意識を向ける機会は少ないだろう。このページでは「時間」に焦点をあててJavaの時間の扱い方についてご紹介する。
目次
Javaでの時間に関するクラスいろいろ
今回は以下のクラスの時間に関する処理について解説する。
クラス |
名前空間 |
内容 |
Dateクラス |
java.util.Date |
日付や時間を扱うことができるクラス |
Calenderクラス |
java.util.Calendar |
日付や時間の操作、計算などを扱うことができるクラス |
SimpleDateFormatクラス |
java.text.SimpleDateFormat |
日付や時間の書式に関するクラス |
Systemクラス |
java.lang.System |
標準入出力などシステムに関する処理を行うクラス |
Systemクラスは処理時間の測定に、それ以外のクラスは時間の設定や取得、計算などに使用するケースが多い。なお、JDK1.8からはjava.timeパッケージという新しいクラスが提供されており、そちらでも時間を扱うことができるが、その紹介はまたの機会に行うこととしよう。
タイムゾーンとは
時間に関するクラスを紹介する前に、まずはタイムゾーンという考え方を理解しておく必要がある。
日本と海外では時差があり、それぞれの地域によって標準となる時間が違うことはご存知のことだろう。この地域によって標準として定められている時間のことをタイムゾーンと呼び、協定世界時間からの時間差で表される。
協定世界時間はUTC(Coordinated Universal Time)は世界標準となる時間のことで、セシウム原子時計によって正確に刻まれる時間だ。それぞれのタイムゾーンはUTCからどれくらい時差があるかで表現され、たとえば日本の場合はUTCと9時間の時差があるため「UTC+9」と表現される。
日本の標準時間はJST(Japan Standard Time)で表現され、UTC+9と同じ時間で表現される。国や地域によってタイムゾーンが異なる為、国や地域を特定しないシステムの開発を行う場合、タイムゾーンに注意する必要があるので覚えておこう。
Dateクラス(java.util.Date)
それでは時間を扱うクラスの紹介を始めよう。このDateクラスは初期のJavaから使われており、単純に時間を取得したいだけの時に使うケースが多い。時間の比較などの処理を行うことも可能だが、表示以外の処理は他のクラスで行われることが多くなっている。
主なメソッド
戻り値の型 |
メソッド |
内容 |
boolean |
after(Date dTime) |
2つのDateを比較し、指定した日時より後の日時かを判定する。 |
boolean |
before(Date dTime) |
2つのDateを比較し、指定した日時より前の日時かを判定する。 |
Object |
clone() |
Dateオブジェクトのコピーを戻す。 |
int |
compareTo(Date dTime) |
2つのDate型を比較し、同じ日時なら0、引数の日時が前の日時なら正の数値、引数の日時が後の日時なら負の数値を返す。 |
boolean |
equals(Object obj) |
2つのDateが同じ日時かどうかを判定する。 |
String |
toString() |
Dateを文字にして戻す。 |
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import java.util.Date; import java.lang.Thread; public class Main { public static void main(String args[]) throws InterruptedException{ //Dateオブジェクトを生成する Date dTime = new Date(); //[1] //時間をずらすため1秒中断 Thread.sleep(1000); //[2] //別のDateオブジェクトを生成する Date dTime2 = new Date(); //[3] //Dateの設定内容を出力 System.out.println("[4] dTimeを表示 : " + dTime.toString()); System.out.println("[5] dTime2を表示 : " + dTime2.toString()); //指定された日時の前後を比較 boolean ret; ret = dTime2.after(dTime); System.out.println("[5] dTime2がdTimeより後の日時か比較 : " + ret); ret = dTime2.before(dTime); System.out.println("[6] dTime2がdTimeより前の日時か比較 : " + ret); ret = dTime2.equals(dTime); System.out.println("[7] 同じ日時かどうか : " + ret); //日時の比較 int diff = dTime.compareTo(dTime2); System.out.println("[8] dTimeとdTime2の比較 : " + diff); } } |
実行結果
1 2 3 4 5 6 |
[4] dTimeを表示 : Thu Jun 23 16:16:35 JST 2016 [5] dTime2を表示 : Thu Jun 23 16:16:36 JST 2016 [5] dTime2がdTimeより後の日時か比較 : true [6] dTime2がdTimeより前の日時か比較 : false [7] 同じ日時かどうか : false [8] dTimeとdTime2の比較 : -1 |
プログラムの説明
それではプログラムを簡単に説明しよう。括弧の番号はサンプルプログラムの実行ステップを意味するので、プログラムと実行結果の関係を把握するための参考としてほしい。
- [1]Dateオブジェクトを新規に作成。
- [2]処理を1秒間だけ止めている。
- [3]別のDateオブジェクトを作成。
- [4]Dateオブジェクトの中身を表示。「JST」というタイムゾーンも表示される。もうひとつのDateオブジェクトは[2]で1秒処理を停止した後に作成したので、1秒だけ違う時間となる。
- [5]dTime2はdTimeより1秒後なので「true」を返す。
- [6]dTime2はdTimeより1秒後なので「false」を返す。
- [7]dTime2とdTimeの時間は異なるので「false」を返す。
- [8]dTime2の方が後の時間なので「-1」を返す。
Dateは標準化対象から外れたクラス
このクラスはJDK1.1以降、javaの標準化対象から外れてしまったクラスであるため、現在では後で説明するCalendarクラスやSimpleDateFormatクラスを多用することが多い。また、Dateクラスが持つメソッドについても、将来的に廃止される可能性のある「非推奨」メソッドが多く含まれるので、使用する際には注意が必要だ。
Calendarクラス(java.util.Calendar)
CalendarクラスはDateクラスよりも使いやすいクラスで、日時の設定はもちろん、日付や時間の計算なども可能だ。
主なメソッド
戻り値の型 |
メソッド |
内容 |
Calendar |
getInstance() |
カレンダーオブジェクトのインスタンスを取得する。 |
int |
get(int field) |
指定したカレンダーフィールド(時、分など)の値を返す。 |
void |
set(int field, int value) |
指定したカレンダフィールドに値を設定する。 |
boolean |
equals(Object obj) |
2つのカレンダーオブジェクトが等しいかどうかを判定する。 |
void |
add(int field, int value) |
指定したカレンダーフィールドの値を加算、減算する。 |
boolean |
after(Object obj) |
2つのCalendarを比較し、指定した日時より後の日時かどうかを判定する。 |
boolean |
before(Object obj) |
2つのCalendarを比較し、指定した日時より前の日時かどうかを判定する。 |
void |
clear() |
カレンダーオブジェクトをクリアする。 |
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
import java.util.Calendar; import java.util.Date; import java.lang.Thread; public class Main { public static void main(String args[]) throws InterruptedException{ Calendar cTime = Calendar.getInstance(); //[1] //主なCalendarクラスの時間関連メソッド //各要素の取得 System.out.println("[2] 時を表示 : " + cTime.get(Calendar.HOUR)); System.out.println("[3] 時(24時間)を表示 : " + cTime.get(Calendar.HOUR_OF_DAY)); System.out.println("[4] 分を表示 : " + cTime.get(Calendar.MINUTE)); System.out.println("[5] 秒を表示 : " + cTime.get(Calendar.SECOND)); System.out.println("[6] ミリ秒を表示 : " + cTime.get(Calendar.MILLISECOND)); System.out.println("[7] AM/PMを表示 : " + cTime.get(Calendar.AM_PM)); //カレンダー時間の設定 cTime.set(Calendar.HOUR_OF_DAY, 23); cTime.set(Calendar.MINUTE, 59); cTime.set(Calendar.SECOND, 59); Date time = cTime.getTime(); System.out.println("[8] setで変更した日付を表示(時分秒を指定) : " + time.toString()); Thread.sleep(1000); Calendar cTime2 = Calendar.getInstance(); Date time2 = cTime2.getTime(); System.out.println("[9] 新しいカレンダーオブジェクトを生成 : " + time2.toString()); //カレンダーの比較 boolean ret; ret = cTime.equals(cTime2); System.out.println("[10] cTimeとcTime2が同じかどうか : " + String.valueOf(ret)); ret = cTime.after(cTime2); System.out.println("[11] cTimeがcTime2より後の時間かどうか : " + String.valueOf(ret)); ret = cTime.before(cTime2); System.out.println("[12] cTimeがcTime2より前の時間かどうか : " + String.valueOf(ret)); cTime.add(Calendar.SECOND, 1); time = cTime.getTime(); System.out.println("[13] cTimeに1秒加算 : " + time.toString()); //値のクリア cTime.clear(); time = cTime.getTime(); System.out.println("[14] 値をクリアする : " + time.toString()); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[2] 時を表示 : 4 [3] 時(24時間)を表示 : 16 [4] 分を表示 : 31 [5] 秒を表示 : 10 [6] ミリ秒を表示 : 188 [7] AM/PMを表示 : 1 [8] setで変更した日付を表示(時分秒を指定) : Thu Jun 23 23:59:59 JST 2016 [9] 新しいカレンダーオブジェクトを生成 : Thu Jun 23 16:31:11 JST 2016 [10] cTimeとcTime2が同じかどうか : false [11] cTimeがcTime2より後の時間かどうか : true [12] cTimeがcTime2より前の時間かどうか : false [13] cTimeに1秒加算 : Fri Jun 24 00:00:00 JST 2016 [14] 値をクリアする : Thu Jan 01 00:00:00 JST 1970 |
プログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1]新しいカレンダーオブジェクトを作成する。
- [2]作成したカレンダーオブジェクトの時刻のうち時を表示する。この指定だと午前、午後の時間(0-11)が表示される。
- [3]時刻のうち時を表示するが、HOUR_OF_DAYでは24時間表記で表示される。
- [4]時刻のうち分を表示する。
- [5]時刻のうち秒を表示する。
- [6]時刻のうちミリ秒を表示する。ちなみにミリとは単位の1/1000を指すので、1000ミリ秒=1秒となる。
- [7]時刻のAM/PMを表示する。AMは「0」、PMは「1」となる。
- [8]カレンダーに時、分、秒を設定して表示している。
- [9]処理を1秒間停止させた後で、新しいカレンダーオブジェクトを作成した。
- [10]cTimeはcTime2と時間が異なるので「false」を返す。
- [11]cTimeはcTime2より後の時間なので「true」を返す。
- [12]cTimeはcTime2より後の時間なので「false」を返す。
- [13]cTime1に1秒加算すると、日付が変わっているのがわかる。
- [14]カレンダーオブジェクトをクリアするとデフォルトの日時が設定される。
定数を指定すると理解しやすいプログラムに
Calendarオブジェクトの値を取得する際、「HOUR」や「MINUTE」などの文字を指定して値を取得しているが、このような文字のことを「定数」と言う。プログラムに書かれる内容が「0」や「1」だと何を意味するのかわかりにくいが、「MINUTE」だと「分」を意味するのがわかるように、定数とは人間に分かりやすい形で値を表現したものである。
Calendarオブジェクトの時間に関する定数には以下のものがあるので、参考にしてほしい。
Calendar定数
定数 |
値 |
AM_PM |
9 |
HOUR |
10 |
HOUR_OF_DAY |
11 |
MINUTE |
12 |
SECOND |
13 |
MILLISECOND |
14 |
SimpleDateFormatクラス(java.text.SimpleDateFormat)
SimpleDateFormatクラスは日付や時間の書式に関するクラスで、指定した書式で日時を表示することができる。データベースへの日時の登録や画面、帳票への出力など、日時の表現で広く使われているクラスだ。
主なコンストラクタ
コンストラクタ |
内容 |
SimpleDateFormat() |
デフォルトの時間書式が設定される。 |
SimpleDateFormat(String pattern) |
パターンで指定した時間書式が設定される。 |
主なメソッド
戻り値の型 |
メソッド |
内容 |
void |
applyPattern(String pattern) |
時間書式を指定する。 |
StringBuffer |
format(Date dt) |
指定した時間書式を適用して表示する。 |
時間の書式について
SimpleDateFormatで使用できる時間に関する書式は以下のとおりだ。
書式 |
内容 |
H |
1日における時(0~23) |
h |
午前/午後の時(0~11) |
m |
分 |
s |
秒 |
S |
ミリ秒 |
a |
午前/午後 |
Z |
タイムゾーン |
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import java.util.Calendar; import java.text.SimpleDateFormat; public class Main { public static void main(String args[]) { //カレンダーを生成 Calendar cTime = Calendar.getInstance(); //フォーマットを設定して出力 SimpleDateFormat sdf = new SimpleDateFormat("[1] h/m/s S"); System.out.println(sdf.format(cTime.getTime())); sdf.applyPattern("[2] a hh時mm分ss秒 SSSミリ秒"); System.out.println(sdf.format(cTime.getTime())); sdf.applyPattern("[3] HH:mm:ss SSS"); System.out.println(sdf.format(cTime.getTime())); sdf.applyPattern("[4] HH:mm:ss Z"); System.out.println(sdf.format(cTime.getTime())); } } |
実行結果
1 2 3 4 |
[1] 5/4/48 827 [2] 午後 05時04分48秒 827ミリ秒 [3] 17:04:48 827 [4] 17:04:48 +0900 |
プログラムの説明
それではSimpleDateFormatのサンプルプログラムを簡単に説明しよう。
- [1]書式を指定してSimpleDateFormatオブジェクトを生成。
- [2]午前/午後、漢字を指定して表示することもできる。なお「HH」など同じ書式を繰り返すことで、「05時」のようにゼロ埋めで表示できる。
- [3]24時間表示で表示している。
- [4]こちらの例ではUTCを表示している。日本で実行しているので「+0900」と表示される。
Systemクラス(java.lang.System)
Systemクラスは名前の通りシステム関連の処理を持つクラスだが、この中でも処理時間の測定に役立つメソッドがあるので紹介しよう。
システム開発で時間がかかる処理がある場合、実際にどれくらい時間がかかるかを測定するケースがあるが、そのような時に役立ててほしい。
主なメソッド
戻り値の型 |
メソッド |
内容 |
long |
currentTimeMillis() |
ミリ秒で表現される現在時間を返す |
long |
nanoTime() |
Java仮想マシンの高精度時間ソースの現在値を、ナノ秒の単位で返す |
サンプルプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class Main { public static void main(String args[]) throws InterruptedException{ //ミリ秒で計測 long startMilli = System.currentTimeMillis(); //空ループを実行 for(long loopA = 0; loopA < 100000000; loopA++){ } long endMilli = System.currentTimeMillis(); System.out.println("[1]処理時間 : " + (endMilli - startMilli) + " ミリ秒"); //ナノ秒で計測 long startNano = System.nanoTime(); //空ループを実行 for(long loopB = 0; loopB < 100000000;loopB ++){ } long endNano = System.nanoTime(); System.out.println("[2]処理時間 : " + (endNano - startNano) + " ナノ秒"); } } |
実行結果
1 2 |
[1]処理時間 : 62 ミリ秒 [2]処理時間 : 59179088 ナノ秒 |
- [1]startMilliでミリ秒を取得し、ループ処理を1億回行った後でendMilliのミリ秒を取得している。取得したミリ秒の差分を求めると、処理時間がどれくらいかかったかを把握できる。それでは簡単にプログラムの説明をしてみよう。
- [2]こちらも[1]と同様に2つの処理の差を求めることで処理時間を把握しているが、こちらはナノ秒単位での計測になる。
ミリとナノの違いについて
currentTimeMillisメソッドでミリ秒単位での計測が可能なように思えるのだが、実際にはOSによって計測単位が大きくなってしまうという特徴があり、正確さに欠けるという問題がある。比較的長い処理をざっくりとした時間で計測したいなら使ってもいいかも知れないが、正確さを求める場合はcurrentTimeMillisメソッド使用しない方がいいだろう。
正確な時間を計測したい場合はgetNanoメソッドを使うといい。これは時間を計測するためだけに使うことができるメソッドで、ほぼナノ秒単位での処理時間の計測が可能だ。ちなみに1ミリ秒=1,000,000ナノ秒なので、かなり高い精度で計測することができるのだ。
時間に関するクラスの基礎をおさえておこう
Javaにおける時間に関するクラスの使い方を紹介したが、いかがだっただろうか?
時間に関する処理では12時間表示や24時間表示、午前午後、ミリ秒、ナノ秒など扱う要素が多いため、ここで紹介した基本的な内容は理解しておくようにしよう。
コメント