時間や時刻について

このエントリーをはてなブックマークに追加

時間関係のプログラミングに入る前に時間、時刻の概念や、OSはどのようにこれらを管理しているのかを先に理解しておく必要があります。
お給料を頂いているプロのプログラマでもこのあたりがいい加減になっている人もいます。どんな時でもまずは基礎からスタートです。

時間と時刻

時間と時刻の違い

Wikipediaの時間時刻ページを見ると、非常に多くの情報があるが、簡単に説明すると、時刻はある時間の流れの一点、つまり何時何分何秒という値になる。それに大して時間はある時刻と時刻の長さ、例えば30分遅刻した、という使い方になります。
つまり、点と線の違いです。日常生活までこれらを気にする必要はさほどあるとは思えませんが、プログラミングを行う上では重要な概念です。


タイムスタンプ

コンピュータ上ではUnix時間と呼ばれるタイムスタンプです。
Unix時間はUTCの1970年01月01日の00時00分00秒からの経過時間(秒)で表されます。これをUnixエポックとも言います。

このUnix時間は通常Unix系OS以外でも広く使われています。システム内部では32bitや64bitの整数で表されています。
非常に単純なシステムですが、少し考えれば分かる通りこれにはオーバーフローが発生する問題があります。32bitの場合UTCで2038年1月19日3時14分7秒が限界となりこれを過ぎると時間が誤作動を起こします。これが有名な2038年問題です。
現在ではこのような問題があるためほとんどのシステムでは64bitになっているはずです。


様々な時間の基準

UTCなどの時間にはいくつかのの種類があります。
通常はそれぞれが生活している地域によっって標準時間が決まっています。例えば日本だと明石市を基準とする日本標準時間です。しかしこれ以外にも様々な基準がありますので代表的な基準時間を挙げます。

名称説明
TAI国際原子時の略で原子時計を元に計算された非常に厳密な時間
UTC世界共通で使う時間です。JSTなどはこの時間を元に差分を計算して求めます
JST明石市を基準位置とする時間です。普段我々が使用している時間です。UTCに9時間足した値がJSTとなります。
GMTUTC以前はこれを代わりに使用していました。イギリスのグリニッジを基準とする時間です。


現在どの時間帯を使用しているかはdateコマンドで分かります。

$ date
2012年  1月 1日 日曜日 09:00:00 JST

このように行の最後にJSTとでているのでJSTを使っている事が分かります。


ローカルタイムを使用していればローカルタイムが優先して表示されます。UTCで表示したければ"-u"オプションを使用します。

$ date -u
2012年  1月 1日 日曜日 00:00:00 UTC


コンピュータ上での時刻

さて、UTCやJSTを使っていることは分かりましたが、この時間は何を元に生成しているのでしょうか?


通常PCにはハードウェアクロックというのが存在します。リアルタイムクロック(RTC)とも言います。
ハードウエアクロックはマザーボード上に物理的に実装されています。つまりOSからは独立しており電源を落としてもマザーボード上のバックアップ電池によって動作し続けます。


それに対してシステムクロックが存在します。これはOS起動時にハードウェアクロックを元に作成した時間で、UTCとして生成されます。
さらに、ローカルタイムを使う必要があればこの時に指定されます。


時間のずれ

現実時間と機械的なずれ

時間を刻み続けている方法は理解しましたが、実際には現実時間とのずれがどうしても出てきます。そもそもPC上の時間はハードウェアで擬似的に作成しているものです。
しかし、正しい時間はTAIですし、ハードウェアとのずれはどうしても発生します。
この"時間のずれ"を修正する為にあるのがNTPです。NTPを使えばシステム時間を自動的に設定してくれます。


OS(Linux Kernel)の割り込み間隔

そもそもOSは一定時間毎に動作します。これにより様々な処理をします。当然時間のカウントもです。
ここではOSの仕組みなどの詳しい話はしませんが、この間隔をtickといい単位をHzで表します。
Linux 2.6系では1000Hz、つまり約1000ナノ秒の精度を持ちます。つまり1000ナノ秒以下のタイマーは実装できません。
これはLinuxをメインの話ですが他Unixの実装でも通用するはずです。例えば、FreeBSD 6.x系列も1000Hzになっていたはずです。(とは言え筆者は他Unixの実装は詳しくないので間違いもあるかと...)

この話が基本になりますが、最近のLinuxだとhrtimerという高精度カーネルタイマが実装されていてこの限りではないようです(ハードウェア次第ですが)。


まとめ

いかがだったでしょうか。ただ単に独立した環境であればさほど問題にはなりませんが、ネットワークを前提にした現代では時間が重要になってきます。また、時間、時刻の概念を知らないと実用的なプログラミングで予想以上にハマる場合もあります。
このページで紹介した内容は本当に基礎の基礎です。これらをしっかり理解して置いてください。
ちなみにさらに実装に絡んだ詳しい説明がmanのtime(7)にあります。このページを理解したのであれば、ぜひ読むべき資料でしょう。