time_t

読み:タイム・ティー
外語:time_t 英語
品詞:名詞

ANSI CやC++で時刻を表わす型。一般に、The Epochからの経過秒数で表現する(ただし、閏秒は数えない)。

目次

C

#include <time.h>

定義は後述。

C++

C++では、std::time_tである。

#include <ctime>

namespace std {

typedef 処理系依存 time_t;

}

定義は後述。

システム時刻の管理、処理のために使われている型である。

ISO C標準はtime_tを数値型と定義するのみで、その範囲や間隔などは定義していない。つまり、規格上は精度が保証されていない。分単位でもBeat単位でも、規格違反ではない。

実際にはUNIXおよびPOSIX互換システムにおいては、The Epochからの経過秒数で処理されている。

但し、time_tは閏秒を数えていないことから、The Epochからの経過秒数に対応する日時と、現実の日時は、厳密には一致していない点に留意が必要(なこともあるかもしれないが無いかもしれない)。

実装

_tで終わる型は大抵はシステムデータ型で、必ずどこかでtypedefされている。元がどのような型であるかは、実装に委ねられている。

従来の実装では32ビット符号付き整数型(signed long int)だが、これは2038年問題を起こす。

32ビットのままでも無符号(unsigned long int)にすれば2106(令和88)年2月7日まで簡単に問題回避が可能だが、Cの日時処理の関数mktime()関数などはエラー時に(time_t)(-1)を返すという仕様があったため、64ビット化しsigned long longを採用することとなった。

このように、signed longではなくtime_tとしていたのは、サイズが変わった時にも対応できるようにした保険の一つだった。

ちなみに、POSIX(IEEE Std 1003.1-2004)仕様では、time_tは整数でも浮動小数点数でも良いとされている。しかしdoublelong doubleでは秒単位が正確に表現できない可能性が高く、浮動小数点数で実装しているシステムは現時点では確認できていない。

上限

各ビットごとの最大日時は次の通り。

  • 31ビット 2038/01/19 03:14:07
  • 32ビット 2106/02/07 06:28:15
  • 33ビット 2242/03/16 12:56:31
  • 34ビット 2514/05/30 01:53:03
  • 35ビット 3058/10/26 03:46:07
  • 36ビット 4147/08/20 07:32:15
  • 37ビット 6325/04/08 15:04:31
  • 38ビット 10680/07/14 06:09:03

(中略)

  • 52ビット 142715360/12/06 03:48:15
  • 53ビット 285428751/11/12 07:36:31
  • 54ビット 570855533/09/22 15:13:03
  • 55ビット 1141709097/06/13 06:26:07

Ubuntu 10.04のgcc 4.4.3とFreeBSDのclang/LLVMで確認したところ、正しいかどうかは不明だがフルビットでは55ビット(0x7fffffffffffff)までは一応動作した。

しかしそれ以上は想定外の問題として、struct tm内のint tm_yearがオーバーフローしてマイナスになってしまい、正常動作しなくなるもよう。要するに、年が31ビットに収まらないといけないということである。

したがって、2147485548/12/31 23:59:59までしか扱えないということになる。このときのtime_tは、0xf0c29d868bfd7fである。つまり21億4748万5548年問題があることになる。

なお、オーバーフロー時、gcc 4.4.3はデタラメな結果を返すが、clang/LLVMは1900/01/00 00:00:00を返す。つまりstruct tmの中をゼロクリアして返却する。

Visual C++

Windows用のC/C++コンパイラーであるVisual C++ 2010(Microsoft C/C++ Version 16)の場合、gmtime()関数で扱えるtime_t値の上限は、0x7934126cfだった。

これは、3001/1/1 20:59:59(UTC)に対応する。つまり、3001年問題が存在することになる。

UNIX愛好家界隈には、time_tパーティ(time_t parties)と称される祝賀会が存在するらしい。

キリ番ゲットのノリで、キリの良い数字になったときに、それを祝うというものであるとされる。

基本的には10進数でキリの良い数字を喜ぶらしく、16進数のキリの良い数字を喜ぶのは一部のグループだけであるらしい。

  • 2001(平成13)年9月9日10:46:40(日本時間)(@115): Unix billennium (UNIX時刻1,000,000,000)
  • 2004(平成16)年1月10日22:37:04(日本時間)(@609): UNIX時刻230 (1,073,741,824)
  • 2005(平成17)年3月18日10:58:31(日本時間)(@123): UNIX時刻1,111,111,111
  • 2009(平成21)年2月14日08:31:30(日本時間)(@021): UNIX時刻1,234,567,890 (UTCでは13日の金曜日だが、国により2月14日バレンタインデー)
  • 2012(平成24)年7月13日20:01:20(日本時間)(@500): UNIX時刻0x50000000 (1,342,177,280) (多くの国で13日の金曜日)

以下は今後起こりうるもの

  • 2021(令和3)年1月14日17:25:36(日本時間)(@392): UNIX時刻0x60000000 (1,610,612,736)
  • 2029(令和11)年7月18日14:49:52(日本時間)(@284): UNIX時刻0x70000000 (1,879,048,192)
  • 2033(令和15)年5月18日12:33:20(日本時間)(@189): second billennium (UNIX時刻2,000,000,000)
  • 2038(令和20)年1月19日12:14:07(日本時間)(@176): 31ビットtime_tの最後 (UNIX時刻0x7fffffff=2,147,483,647)

Visual C++ 6

古いVC++に限らず、古い処理系は概ね同じ。

Microsoft Visual C++ 2003

Microsoft Visual C++ 2003環境では、次のように定義される。

  • typedef _W64 long time_t; (Win32)
  • typedef __int64 time_t; (Win64)

つまりWin32環境では31ビット長、Win64環境では63ビット長である(有効桁数が1ビット足りないのは符号があるため)。

_W64は、Visual C++ 32bitの場合__w64キーワードに展開される。これは、/Wp64を指定した時に、64ビット対応の型であると指定するものである。

Microsoft Visual C++ 2005/2008

Microsoft Visual C++ 2005/2008環境でも同様であるが、若干定義が異なる。

  • (crtdefs.h) typedef __int64 __time64_t;
  • (crtdefs.h) typedef __time64_t time_t;

Win32環境でも__int64は利用可能で、もってtime_tは64ビット化されている。

FreeBSD

time.hなど

typedef __time_t time_t;

stddef.h → sys/_types.h → machine/_types.h と間接的に呼ばれた /usr/include/machine/_types.h で、次のように定義される。

typedef int __int32_t;

typedef long __int64_t;

(32ビットFreeBSDの場合)

typedef __int32_t __time_t;

(64ビットFreeBSDの場合)

typedef __int64_t __time_t;

FreeBSDでは、間接的にintまたはlongで定義される。もって64ビット版ではtime_tは64ビット化されている。

LINUX

カーネル内

Linuxカーネルでは、次のように定義される。

include/linux/types.h

typedef __kernel_time_t time_t;

__kernel_size_tの定義は環境ごとに様々であるが、代表的な環境(x86とARM)では次のようになっている。

x86の32ビットの場合、arch/x86/include/asm/posix_types_32.h で定義される。

typedef long __kernel_time_t;

x86の64ビットの場合、arch/x86/include/asm/posix_types_64.h で定義される。

typedef long __kernel_time_t;

ARMの32ビットの場合、arch/arm/include/asm/posix_types.h で定義される。

typedef long __kernel_time_t;

概ね、32ビット環境/64ビット環境問わずlongで間接的に定義されるようになっている。もってtime_tは64ビット環境において64ビット化されている。

ユーザー空間

time.h → bits/time.h → bits/types.h と間接的に呼ばれた /usr/include/bits/types.h で、次のように定義される。

# define __STD_TYPE __extension__ typedef (32ビットの場合)

# define __STD_TYPE typedef (64ビットの場合)

__STD_TYPE __TIME_T_TYPE __time_t;

/usr/include/bits/typesizes.h

#define __TIME_T_TYPE __SLONGWORD_TYPE

/usr/include/bits/types.h

#define __SLONGWORD_TYPE long int

LINUXでは、32ビット/64ビット問わず、間接的にlongで定義される。もってtime_tは64ビット環境において64ビット化されている。

Java

Javaは、Cのtime_t互換の仕様は導入せず、独自のjava.util.Dateクラスを用いて日時を管理する。

従って2038年問題など、Cに存在する問題は生じない。

現時点では処理できる実装はないが、符号付き64ビットのtime_tでは、1ビットが符号となるため有効63ビットで、0x7fffffffffffffffまでを扱うことができる。

つまり64ビットtime_tは、1970年1月1日00:00:00(UTC)+0x7fffffffffffffff秒までの時刻表現が保証される。

最大値となる0x7fffffffffffffffの場合、閏年などの計算方法が今と変わらないという前提では、西暦2922億7702万6596年12月4日 15:30:07(UTC)まで表現できると計算できる。つまり、2922億7702万6596年問題が生じることが分かる。もっとも、現在、太陽の主系列星としての寿命は109億年とされ、太陽は寿命半ばの約46億歳と考えられていることから、この問題が生じる頃には既に地球はないか、仮にあったとしても人類が地球上に存在していない可能性が高い。

実際には、struct tmの仕様上の制限から、その全ての時刻を扱うことはできないが、少なくとも21億4748万3647年までは扱うことが可能である。

つまり、64ビット化は、単に問題を21億年あるいは2900億年ほど先送りしたに過ぎず、後々問題が発生する可能性があり、これを「2922億年問題」という。なお、これは宇宙の年齢(約137億年)の21倍程度という年月に相当する。

用語の所属
_t
関連する用語
The Epoch
2038年問題
20XX年問題
FILETIME
UNIX時間

コメントなどを投稿するフォームは、日本語対応時のみ表示されます


KisoDic通信用語の基礎知識検索システム WDIC Explorer Version 7.04a (27-May-2022)
Search System : Copyright © Mirai corporation
Dictionary : Copyright © WDIC Creators club