
プログラマーの常識をJavaで身につける (4)
OSとプログラミングの「時間」に関する常識
NTTデータ ビジネスブレインズ
伊賀敏樹
2007/3/28
本連載は、Java言語やその文法は一通り理解しているが、「プログラマー」としては初心者、という方を対象とします。Javaコアパッケージを掘り下げることにより「プログラマーの常識」を身に付けられるように話を進めていきます(編集部注:Java言語の基礎を学びたい読者は、連載「Eclipseではじめるプログラミング」や連載「いまから始めるJava」をご参照ください)。
| 今回の主な内容 ・ デスクトップなど身近なところに現れる日付・時刻 ・ Java言語における日時を表すクラス・型 ・ OSから現在時刻を取得するには? ・ 相互変換で日付・時刻のクラスを使いこなそう! ・ 日時を文字列へ変換 ・ タイマーとタスクって何だ? ・ 次回は「国際化プログラミング」の常識について |
今回の記事では、「時間」に関する常識を Javaで身に付けていきます。時間の扱い方は、前回説明した「数」の扱い方と同様で、プログラミング言語によって特徴が出やすいものです。Java言語を通じて、時間の取り扱い方を見ていくことにより、プログラマーとしての常識を身に付けていきましょう。
デスクトップなど身近なところに現れる日付・時刻
プログラミングの話題に入る前に、まず私たちの身近なところに現れる日付や時刻を見ていきましょう。あなたがお使いのOSがWindows XPでしたら、デフォルトの設定では、タスクバーの通知領域に時計が表示されていると思います。
| 図1 通知領域に表示される時計 |
時計の部分をダブルクリックすると、 「日付と時刻のプロパティ」画面を開くことができます。
![]() |
| 図2 日付と時刻のプロパティ(日付と時刻) |
■ リアルタイムクロックとシステムクロックとは?
この画面には、日付と時刻が表示されます。ここで表示されている日付および時刻は、OSが内部的に保持している日時となります。OSが刻んでいる時計は システムクロック(システム時計)と呼ばれます。
一方で、OSが起動していない間にも時刻を刻んでいる必要があります。これを実現するために、コンピュータにはリアルタイムクロック(ハードウェアクロック)と呼ばれる時計が内蔵されています。
Windows XPなどのOSは、起動時にリアルタイムクロックから時刻を取得して、その後、OSとしてのシステム時計の時刻を刻むようになっています。私たちが普段何げなく利用しているOSの時計ですが、二重構造の時計として実装されているのは、意外なことです。
コラム 「OSの時計は不正確」 |
| 原稿執筆時点において、私たちの身近なパソコンのOS上で表示される時計は、意外なほどに不正確です。プログラムから日時を扱うプログラミングをする場合にも、この点に注意を払う必要があります。 |
■ 時差を表すタイムゾーン
先ほどの「日付と時刻のプロパティ」画面の「タイムゾーン」タブを選択すると、タイムゾーンを選択する画面が表示されます。
![]() |
| 図3 日付と時刻のプロパティ(タイムゾーン) |
最近のOSの多くはGMT(グリニッジ標準時)によって定義された標準にのっとっています。そして、java.util.CalendarなどJava言語の日時についても、GMTを基準とした仕組みになっています。この画面に表示があるように、グリニッジと日本では、9時間の時差があります。
Java言語における日時を表すクラス・型
それでは、Java言語における日付・時刻を見ていきましょう。Java言語には、図4のように主に3つの日付・時刻を表す型や数値があります。そして、それらは日時を表すようになっています(※注釈:これ以外にもいくつかの型があります)。歴史的な経緯もあり、これら型や数値の間には、いくぶん癖のある関係があります。
![]() |
| 図4 Java言語における日付・時刻 |
それぞれについて見ていきましょう。
■ 「エポックからのミリ秒」というlong値による日時の表現
コンピュータ関連技術の多くでは、日時を整数で表す手法が採用されています。整数はコンピュータ処理しやすいからでしょう。Java言語も日時を整数で表す方法を採用しています。
具体的には、1970年1月1日 00:00:00 GMTからのミリ秒数を表すlong値として表現されています。この原稿では、これを便宜的に「エポックからのミリ秒」と呼ぶことにします。なお、1970年1月1日 00:00:00 GMTについてJava言語APIでは、「エポック」と呼んでいます。
![]() |
| 図5 「エポック」から現在へ |
■ [java.util.Date]による日時の表現
Java言語には、日時を表すクラスとしてjava.util.Dateクラスが提供されています。クラス名も、それが日付を表す重要なクラスであることを示唆しています。しかし、java.util.Dateクラスの大半のメソッドは推奨されない(deprecated)メソッドとしてマークされています。
java.util.DateのAPIドキュメントに記載があるように、歴史的な経緯から「日付と時間フィールドの間の変換には、Calendarクラスを、日付文字列のフォーマットと構文解析には、DateFormatクラスを使用する」(ここはAPIドキュメントから引用しています)ことになっているのです。とはいえ、日時を表現するクラスとして、java.util.Dateはよく利用されます。
注意 Dateクラスは別パッケージにも存在する[java.sql.Date] |
||
Java言語APIには、java.util.Dateクラスに似た名前のjava.sql.Dateクラスがあります。パッケージ名を除くと、まったく同じ名称なので混同しないよう注意が必要です。例えば、Eclipseなどの統合開発環境において、入力補完やインポートの編成などの機能を利用すると、以下のような選択肢が表示されます。ここでどちらのクラスを利用するのか、適切に選択する必要があります。
編集部注:2つのDateクラスについて詳しく知りたい読者は、Java TIPSの「SQLを使うプログラムではDateクラスに要注意」をご参照ください |
■ [java.util.Calendar]による日時の表現
Java言語では、日付や時間の各種変換にはjava.util.Calendarクラスが利用されます。特にget/setメソッドがよく利用されるようです。なお、Calendarクラスのget/setメソッドの呼び出しには、Calendarクラスの定数の利用が必要になるので、主立ったものを以下に紹介します。
| 表1 java.util.Calendarクラスの主な定数 | ||||||||||||||||||||||||
|
特に、月が0オリジンである点に注意する必要があります。
■ [java.util.GregorianCalendar]はハイブリッドカレンダー
java.util.Calendarクラスは抽象クラスです。Calendarクラスのインスタンスとして実際にはjava.util.GregorianCalendarクラスが利用されます。下記のソースコードを実行してください。
| CalendarSample.java | |
|
実行結果 |
| java.util.Calendarクラスの実行時の具象クラス: class java.util.GregorianCalendar |
getInstanceしてgetClass→toStringすると、GregorianCalendarクラスであることが確認できます。
また、java.util.GregorianCalendarのAPIドキュメントには、以下のような記載があります。
| GregorianCalendarは、Calendarの具象サブクラスであり、世界のほとんどの地域で使用される標準的なカレンダシステムを提供します。GregorianCalendar は、グレゴリオ暦とユリウス暦をサポートするハイブリッドカレンダシステムで、単一の変わり目を処理します。 …中略… 歴史的に、グレゴリオ暦を最初に採用した国々では、1582年10月4日(ユリウス歴)の後に 1582年10月15日(グレゴリオ歴)が続きました。 |
本当にそうなっているのか、実際に試してみましょう。下記のソースコードを実行してください。SimpleDateFormatクラスについては、後述します。
| GregorianCalendarSample.java | |
|
実行結果 |
| 1582/10/17 1582/10/16 1582/10/15 1582/10/04 1582/10/03 1582/10/02 |
本当に日付が飛ぶところが確認できました。桃色の日付と赤色の日付の間に、グレゴリオ暦とユリウス暦の境界があります。
■ ほかのクラスにおける日時
ほかのクラスで日時を表す際には、いままで紹介した日時を表す型が利用されることが多いです。
例えば、java.io.Fileクラスにおいて、ファイル最終更新日時はFile.lastModified()メソッドで取得できます。個々で得られるlong値は、「エポックからのミリ秒」なのです。
1/3 |
| Index | ||||||||
|
||||||||
プログラマーの常識をJavaで身につける バックナンバー
| Java Solution全記事一覧 |
TechTargetジャパン
- Scalaのパッケージ、アクセス修飾子、オブジェクト継承 (2012/5/22)
インポート、パッケージオブジェクト、抽象クラス/抽象メソッド、オーバーライド、final、シールドクラスなども - 基幹系システムでCloud SQLは使えるか試してみた (2012/5/17)
サンプルとしてMRPシステムを作成して動かし、「再帰呼び出し」などのパフォーマンスを測定して検証してみます - アジャイル管理ツール9選+Pivotal Tracker入門 (2012/5/14)
群雄割拠のアジャイルプロジェクト管理ツールを9つ紹介し、特に注目を集めているPivotal Trackerの基本的な使い方を解説します - サーバサイドJSやJavaでWebアプリが作れるXPages (2012/5/11)
Notes/Dominoの資産をサーバサイドJavaScriptやJavaで操作し、HTMLやJavaScript、CSSをUIにできる技術を紹介
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -





