Time t

`'''time_t'''`型は、C言語においてシステム時刻を表現あるいは保存するために標準Cライブラリが定義しているデータ型である。この値は標準ライブラリ関数の`'''time()'''`によって得られる。このデータ型は、標準ヘッダファイルの`[[time.h|<time.h>]]`でtypedefによって定義されている。Cの国際標準規格ISO/IEC 9899:1999（通称C99）では、`time_t`を算術型 () と規定しており、またISO/IEC 9899:2011（通称C11）では実数型 () と規定しているが、実際の型・値の範囲・周期や、エンコーディング方法は規定しておらず、実装定義 () としている。また、時刻の値に対する算術演算の動作は定義していない（2つの`time_t`型の値の差を求めるには`difftime()`を用いる）。

UNIXとPOSIX互換システムでは、UNIX時間（協定世界時 (UTC) 1970年1月1日0時00分00秒からの秒数）を表す符号付の整数（通常は32ビットまたは64ビット）で`time_t`型を実装している（閏秒は数えない）。では、負の時刻値をサポートするが、サポートしないシステムもある。2038年問題のために、32ビットの`time_t`は非難されている。
そのため、のシステムには、`time_t`を64ビットの整数型として定義しているものが多いが、古いシステムではそうでないものもあるので注意が必要である。

ISO Cでは、`time()`関数だけでなく、システム時刻`time_t`の値をカレンダー時刻に変換する関数や、逆の変換を行なう関数などを定義している。

## 利用例
以下のC言語のコードは現在時刻を`time_t`型の値として取得し、文字列に変換して標準出力に出力する例である。


```c
#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`は、「要素別の時刻」() と呼ばれるカレンダー時刻の構成要素集合を保持する構造体である。C99において、`tm`構造体は少なくとも下記のメンバーを任意の順序で含むように規定されている（実装によっては他の追加メンバーを含んでいることもある）。そのため、何らかの関数を使って`time_t`の値から`tm`構造体の値を得た後、これらのメンバーを直接読み取って日時情報を取得することも可能である。文字列への書式化に`strftime()`を使う必要はなく、printf系の関数を使うこともできる。

```c
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`が含まれている。

前述のコード例で使用されている`localtime()`関数は、`time_t`の値をローカル時刻として`tm`構造体の値に変換し、そのアドレスを指すポインタを返す。他にもUTC時刻として変換して返す`gmtime()`関数も規定されている。しかし、これらの関数は仕様に欠陥があり、再入可能性やスレッドセーフ性が保証されない。スレッドの概念が標準化されたC11では、変換結果の出力先へのポインタ`struct tm*`を引数として別途受け取るスレッドセーフバージョンの`localtime_s()`と`gmtime_s()`が標準化されたが、境界チェック付き関数と同様、必須機能ではなくオプションである。

POSIXでは、変換結果の出力先へのポインタを引数として別途受け取り、再入可能性とスレッドセーフ性を保証した`localtime_r()`/`gmtime_r()`が規定されている。C23ではPOSIXベースの`localtime_r()`/`gmtime_r()`が標準化される予定である。

Microsoft Visual C++ (MSVC) では、呼び出しスレッドごとに変数の記憶域を確保するスレッドローカルストレージを`localtime()`/`gmtime()`の実装に用いることで、スレッドセーフ性を実現している。また、変換結果の出力先へのポインタを引数として別途受け取る`localtime_s()`/`gmtime_s()`も用意されている。ただし、POSIXの`localtime_r()`/`gmtime_r()`や、C11の`localtime_s()`/`gmtime_s()`とは互換性がない。

`strftime()`は現在設定されているロケール`LC_TIME`の影響を受ける。書式文字列における変換指定子`%Z`は、ロケールのタイムゾーンの名前または略称 () によって置換されるが、タイムゾーン情報が判定できない場合は空文字列となる。変換指定子`%z`は、ISO 8601形式でUTCからのオフセット（`+hhmm`または`-hhmm`）によって置換されるが、タイムゾーン情報が判定できない場合は空文字列となる。`%z`はもともとGNU拡張だったものがC99とPOSIX.1-2001で標準化された。MSVCの実装では、タイムゾーン情報はグローバル変数`_timezone`と`_dstbias`を経由して追加投入されるため、`gmtime()`が返す`tm`構造体へのポインタを`strftime()`に渡した場合、`%Z`や`%z`によって出力される結果は不正確なものとなる。POSIXではタイムゾーン情報を表す環境変数`TZ`が使用されるが、`tm`構造体の値を各種関数呼び出しによって生成した後に`TZ`の値が変更された場合、`%Z`や`%z`によって出力される結果は未定義となる。

## time_tパーティ

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ライブラリ
* リアルタイムクロック
* システム時刻
* UNIX時間
* 2038年問題