現在時刻を求める

こんにちは、めのんです!

今回はCで現在時刻を求める方法を解説します。
規格上、この部分は処理系定義の要素が大きくて、中には全然使いものにならないような実装もあり得るんですけど、ここでは典型的な実装を対象に解説することにします。

暦時間を求める

PHPにはUnixタイムスタンプを求めるtime関数というのがあると思います。
Cのtime関数に対応したものだと思いますが、Cのtime関数はもっと仕様に自由度があります。

「自由度がある」というと聞こえがいいんですけど、移植性に支障があるような実装がいくらでもできるという意味です。

時間を扱うためのCのライブラリを使うには「time.h」ヘッダを取り込む必要があります。
「time.h」の中でtime_t型という型が定義されているんですけど、この型は算術型であること以外何も規定されていません。

そして、time_t型の値を返すのが「time関数」です。
time関数は「time.h」で次のように宣言されます。

time_t time(time_t *timer);

歴史的な理由でポインタを引数に取るらしいんですけど、引数にはNULLを渡して返却値を使えばいいと思います。

ところでこのtime関数ですけど、失敗することもあるんですよね。
昔でいえば2000年問題とか、もう少し最近なら2038年問題のような表現範囲を超えてエラーということもあるんでしょうけど、そもそもRTCもなければNTPなど外部から現在時刻を取得することもできない環境もあるんです。
そういう場合は(time_t)-1を返すことになります。

さっきも書きましたがtime_t型は算術型であること以外何も決まっていません。
精度も表現範囲も処理系定義なんです。
その上、time関数の仕様は次のようになっています。

time関数は,現在の暦時刻を処理系の最良の近似で返す。

実際にそんなことはないでしょうけど、いつも同じ値を返したとしても規格上は問題なさそうです。
多くの場合は秒単位の値を返すか、失敗するかのどちらかだと思います。

暦時間の差

time関数で暦時間を求めても、単位がわかりませんから時刻間のさが求めることもできません。
そんなときには「difftime関数」を使います。

difftime関数の「time.h」で次のように宣言されています。

double difftime(time_t time1, time_t time0);

この関数はtime0からtime1までの経過秒数をdouble型で返します。
それだけです。
ですが、time_t型の値の差を求めるときは必ずdifftime関数を使うようにしてください。

地域時間の取得

地域時間を取得するには「localtime関数」を使います。
PHPにも同名の関数があるのでなじみがあるのではないでしょうか?

Cのloacltime関数は「time.h」で次のように宣言されています。

struct tm *localtime(const time_t *timer);

localtime関数はtime_t型の値をポインタで受け取って(面倒ですねー)、struct tm構造体へのポインタを返します。

返却値のポインタが指す領域は、この関数を呼び出すために再利用されますので、あまり長い間ポインタを持ち回るべきではないと思います。
構造体の内容をコピーして利用するのであれば問題ありません。

struct tm構造体のメンバには次のものがあります。
メンバの順序に関しては処理系定義なので、順序に依存したコードは書かないようにしましょう。

  • tm_sec
  • tm_min
  • tm_hour
  • tm_mday
  • tm_mon
  • tm_year
  • tm_wday
  • tm_yday
  • tm_isdst

各メンバの意味は、PHPのtime関数をassociative=TRUEで呼び出したときと同じです。
唯一異なるのはtm_secの範囲がCでは0から60になることで、閏秒を表現できるようになっています。

ほかにも時間関係のライブラリ機能はいくつかあるんですが、暦時間に関してはこの程度を理解しておけばほとんどの場合大丈夫だと思います。


本日の解説は以上となります。
次回は疑似乱数について解説しようと思います。
どうぞご期待ください!