time_t
型は、C言語 においてシステム時刻 を表現あるいは保存するために標準Cライブラリ が定義しているデータ型 である。この値は標準ライブラリ関数 のtime()
によって得られる。このデータ型は、標準ヘッダファイル の<time.h>
でtypedef によって定義されている。Cの国際標準規格ISO/IEC 9899:1999(通称C99 )では、time_t
を算術型 (arithmetic type [ 1] [ 2] [ 注釈 1] ) と規定しており、またISO/IEC 9899:2011(通称C11 )では実数型 (real type [ 3] [ 4] [ 注釈 2] ) と規定しているが、実際の型・値の範囲・周期 や、エンコーディング方法は規定しておらず、実装定義 (implementation-defined ) としている。また、時刻の値に対する算術演算の動作は定義していない(2つのtime_t
型の値の差を求めるにはdifftime()
を用いる)。
UNIX とPOSIX互換システム では、UNIX時間 (協定世界時 (UTC) 1970年 1月1日 0時 00分 00秒 からの秒数)を表す符号付の整数(通常は32ビット または64ビット )でtime_t
型を実装している(閏秒 は数えない)。いくつかのシステム [要説明 ] では、負の時刻値をサポートするが、サポートしないシステムもある。2038年問題 のために、32ビット のtime_t
は非難されている[ 5] 。
そのため、最近 [いつ? ] のシステムには、time_t
を64ビット の整数型として定義しているものが多いが、古いシステムではそうでないものもあるので注意が必要である。
ISO Cでは、time()
関数だけでなく、システム時刻 time_t
の値をカレンダー時刻 に変換する関数や、逆の変換を行なう関数などを定義している。
利用例
以下のC言語のコードは現在時刻をtime_t
型の値として取得し、文字列 に変換して標準出力 に出力する例である。
#include <stdio.h>
#include <time.h>
/*
* The result should look something like
* Fri 2008-08-22 15:21:59 WAST
*/
int main ( void )
{
time_t now ;
struct tm * ts ;
char buf [ 80 ];
// Get the current time
now = time ( NULL );
// Format and print the time, "ddd yyyy-mm-dd hh:mm:ss zzz"
ts = localtime ( & now );
strftime ( buf , sizeof ( buf ), "%a %Y-%m-%d %H:%M:%S %Z" , ts );
printf ( "%s \n " , buf );
printf ( "%lld \n " , ( long long ) now );
return 0 ;
}
tm
は、「要素別の時刻」(broken-down time ) と呼ばれるカレンダー時刻の構成要素集合を保持する構造体 である。C99において、tm
構造体は少なくとも下記のメンバーを任意の順序で含むように規定されている(実装によっては他の追加メンバーを含んでいることもある)。そのため、何らかの関数を使ってtime_t
の値からtm
構造体の値を得た後、これらのメンバーを直接読み取って日時情報を取得することも可能である。文字列への書式化にstrftime()
を使う必要はなく、printf 系の関数を使うこともできる。
struct tm {
int tm_sec ; // seconds after the minute — [0, 60]
int tm_min ; // minutes after the hour — [0, 59]
int tm_hour ; // hours since midnight — [0, 23]
int tm_mday ; // day of the month — [1, 31]
int tm_mon ; // months since January — [0, 11]
int tm_year ; // years since 1900
int tm_wday ; // days since Sunday — [0, 6]
int tm_yday ; // days since January 1 — [0, 365]
int tm_isdst ; // Daylight Saving Time flag
};
BSD/GNU拡張では、tm
構造体に追加のメンバーtm_gmtoff
とtm_zone
が含まれている[ 6] 。
前述のコード例で使用されているlocaltime()
関数は、time_t
の値をローカル時刻としてtm
構造体の値に変換し、そのアドレスを指すポインタを返す。他にもUTC時刻として変換して返すgmtime()
関数も規定されている。しかし、これらの関数は仕様に欠陥があり、リエントラント 性やスレッドセーフ 性が保証されない。スレッド の概念が標準化されたC11では、変換結果の出力先へのポインタstruct tm*
を引数として別途受け取るスレッドセーフバージョンのlocaltime_s()
とgmtime_s()
が標準化されたが、境界チェック付き関数と同様、必須機能ではなくオプションである[ 7] [ 8] 。
POSIXでは、変換結果の出力先へのポインタを引数として別途受け取り、リエントラント性とスレッドセーフ性を保証したlocaltime_r()
/gmtime_r()
が規定されている[ 9] [ 10] 。C23ではPOSIXベースのlocaltime_r()
/gmtime_r()
が標準化される予定である[ 7] [ 8] 。
Microsoft Visual C++ (MSVC) では、呼び出しスレッドごとに変数の記憶域を確保するスレッドローカルストレージ をlocaltime()
/gmtime()
の実装に用いることで、スレッドセーフ性を実現している[ 11] [ 12] 。また、変換結果の出力先へのポインタを引数として別途受け取るlocaltime_s()
/gmtime_s()
も用意されている[ 13] [ 14] 。ただし、POSIXのlocaltime_r()
/gmtime_r()
や、C11のlocaltime_s()
/gmtime_s()
とは互換性がない。
strftime()
は現在設定されているロケールLC_TIME
の影響を受ける。書式文字列における変換指定子%Z
は、ロケールのタイムゾーンの名前または略称 (abbreviation ) によって置換されるが、タイムゾーン情報が判定できない場合は空文字列となる。変換指定子%z
は、ISO 8601 形式でUTCからのオフセット(+hhmm
または-hhmm
)によって置換されるが、タイムゾーン情報が判定できない場合は空文字列となる。%z
はもともとGNU拡張だったものがC99とPOSIX.1-2001で標準化された[ 15] 。MSVCの実装では、タイムゾーン情報はグローバル変数_timezone
と_dstbias
を経由して追加投入されるため、gmtime()
が返すtm
構造体へのポインタをstrftime()
に渡した場合、%Z
や%z
によって出力される結果は不正確なものとなる[ 16] 。POSIXではタイムゾーン情報を表す環境変数TZ
が使用されるが、tm
構造体の値を各種関数呼び出しによって生成した後にTZ
の値が変更された場合、%Z
や%z
によって出力される結果は未定義となる[ 17] 。
time_tパーティ
この節には独自研究 が含まれているおそれがあります。 問題箇所を検証 し出典を追加 して、記事の改善にご協力ください。議論はノート を参照してください。(2021年7月 )
UNIXファンは、UNIX時間 の意味ありげな値を祝賀するためにtime_tパーティ を行なってきた歴史がある。これは、多くの暦で年が変わるときに行われる新年 パーティと良く似ている。UNIX時間の使用が広がったことで、マイルストーンを祝うことが習慣となった。通常は端数のない10進数 の時刻の値が、time_t の値を10進数で眺めるUNIXのコンベンションで祝賀される。一部のグループは、2004年 1月10日 の13:37:04 UTC に起こった+230 のような端数のない2進数 も祝賀している。
これらの祝賀イベントは、通常は「UNIX epochからN秒」と呼ばれるが、これは不正確である。上で述べたとおり、UNIX時刻の閏秒 の扱いのため、UNIX epochからの秒数はUNIX時刻の数よりもわずかに大きい。
2001年 9月9日 01:46:40 UTC 、UNIX billennium (UNIX時刻が1000000000)の祝賀が行なわれた。
2005年 3月18日 01:58:31 UTC 、UNIX時刻が1111111111に到達した。
2009年 2月13日 23:31:30 UTC 、UNIX時刻が1234567890に到達し、世界中のさまざまなテクノロジーサブカルチャーの間でパーティーやその他の祝賀会が開催された。
2033年 5月18日 03:33:20 UTC 、2回目のUNIX billennium(UNIX時刻が2000000000)の祝賀が行なわれる予定。
脚注
注釈
^ C規格における算術型は整数型 と浮動小数点数 型の総称である。浮動小数点数型には、C99で追加された複素数 型や虚数 型も含まれる。
^ C規格における実数型は整数型と実浮動小数点数型の総称である。実浮動小数点数型には、複素数型や虚数型は含まれない。
出典
^ ISO/IEC 9899:1999, §7.23.1 Components of time, ¶3
^ ISO/IEC 9899:TC3 WG14/N1256 Committee Draft
^ ISO/IEC 9899:2011, §7.27.1 Components of time, ¶3
^ ISO/IEC 9899:201x N1570 Committee Draft
^ The Year 2038 problem , Roger M. Wilcox. Retrieved on 2008年 5月19日 .
^ Broken-down Time (The GNU C Library)
^ a b localtime, localtime_r, localtime_s - cppreference.com
^ a b gmtime, gmtime_r, gmtime_s - cppreference.com
^ localtime, localtime_r - convert a time value to a broken-down local time | The Open Group Base Specifications Issue 6 / IEEE Std 1003.1, 2004 Edition
^ gmtime, gmtime_r - convert a time value to a broken-down UTC time | The Open Group Base Specifications Issue 6 / IEEE Std 1003.1, 2004 Edition
^ localtime, _localtime32, _localtime64 | Microsoft Learn
^ gmtime, _gmtime32, _gmtime64 | Microsoft Learn
^ localtime_s, _localtime32_s, _localtime64_s | Microsoft Learn
^ gmtime_s, _gmtime32_s, _gmtime64_s | Microsoft Learn
^ Formatting Calendar Time (The GNU C Library)
^ strftime, wcsftime, _strftime_l, _wcsftime_l | Microsoft Learn
^ strftime - convert date and time to a string | The Open Group Base Specifications Issue 6 / IEEE Std 1003.1, 2004 Edition
関連項目