English

第99回コラム
日時の表現

情報アーキテクチャ専攻 小山 裕司 教授

現在の私達の生活では「平成30年4月3日(水) 11:00」等の日時の概念の常に付きまとう。私達は日常的に日時を使い込んでいるので、困惑することは稀であるが、日時の概念は結構複雑である。

多くの国では、年をカウントする紀年法として、キリストが生まれたとされる年の翌年を元年とした紀年法である西暦が普及している。日本でも西暦が一般的には使われているが、日本の公の機関では紀年法として基本的に和暦が使われ、和暦も西暦同様一般的に使われている。和暦は、平成等の日本独自の元号(称号・単位)と年数によって年を表現する日本独自の紀年法で、現在、元号は天皇の皇位を継承する際にのみ改められるが、昔は各種の理由で改元されていた。最初の元号は「大化の改新」で知られる「大化」であり、南北朝時代には重複していたり、元号が無かった期間があったりするが、平成は250番目の元号らしい。

現在の西暦でも和暦でも、グレゴリオ暦(いわゆる新暦)と呼ばれる同じ暦法によって、年の暦が決まっているため、西暦・和暦間の換算は単純であるが、このほかにも太陰太陽暦、干支紀年法等、ユリウス暦等の旧暦が使われていたり、使われていることがあるので、歴史上のイベントを考察するとき等には日付のズレも意識する必要がある。またイスラム暦は現在でも太陰暦である。

西暦でも和暦でも、秒と分は60進法、時は12あるいは24進法、月は12進法で表現され、日は30か31、また2月だけは28、うるう年では29で桁上りが生じる。余談であるが、情報の基礎科目で、2進法、8進法、16進法等を取り上げると、普段の生活であまりに10進法に慣れているため、困惑されることが多いが、日時の表現を例にあげれば、困惑が概ね収まる。60進法は、古代文明で知られるメソポタミア文明の初期の、突如現れた謎の文明という噂もあるシュメール文明が紀元前3000年頃から使い始めたという逸話も一緒に話をすることにしている。

時刻には以前のグリニッジ標準時に相当する協定世界時UTCがあり、地域ごとに標準時が設定されている。現在39種類の標準時間帯が存在し、協定標準時UTCとの時差で示される。日本標準時JSTはUTC-9であり、オーストラリア東部時間AESTはUTC-10であるため、日本の時刻はシドニーより1時間遅れている。また、地域によっては夏季には夏時間が設定され、さらに夏時間の設定は地域で様々である。オーストラリアは南半球であるため、4月第1日曜までは夏時間でオーストラリア東部時間AESTがUTC-11に変わっているため、日本時間が2時間遅れる。

このように書き出してみると、私達が日常使っている日時もいろいろと複雑である。現在の情報システムでは、日時の扱いは不可欠であるため、次にIT領域での日時の話をしたいと思う。

IT領域では、Y2Kと呼ばれた2000年問題が20年前に隆起した。昔のソフトウェアでは節約のため1998等を単に略して98と2桁で表現していたものが多く、実装によっては桁上りが無視され、2000年が00年、1900年、19100年等と誤って扱われる問題である。2000年ごろはすでにITが社会インフラの裏側には広く普及していたため、2000年問題によるIT機器の誤作動によって生じる各種の危機が叫ばれていたが、事前の対処が功を奏して大事は回避された。当事WebのCGI等で人気を博していたPerlは、1986年に生まれた、当事はまだ若いプログラミング言語であったが、2000年問題を誘発する仕様のlocaltime関数があったため、誤用に気付いてもらうために「Year 2000 Compliance: Lawyers, Liars, and Perl」というPerlは2000年準拠だと自慢する記事がPerl公式サイトに掲載されたりもした。

ソフトウェアの内部での日時の扱いの話を続ける。Unixを起源とするOSあるいはプログラミング言語では、現在時刻は日時はエポックからの経過秒数で取得することができることが多い。エポックは通常UTCの1970年1月1日時0分0秒であり、2018年04月03日(火) 11:00は1522720800である。 この経過秒数を保存するオブジェクトのデータ型はtime_t型であり、昔は32-bitの符号付き整数(signed int)であったため、20年後の2038年にはオーバーフローが生じ、誤動作が生じる恐れがある。これが2038年問題と呼ばれる問題である。最近のOS及びプログラミング言語処理系ではtime_t型を64-bitの符号付き整数で実装するという対処をしているが、現在流通しているあらゆるソフトウェアが対処できている訳では無い。

エポックからの経過秒数という日時の表現は極めて単純である。何かの経過時間を調べたいのであれば、この値の差を計算すればいいのだが、日付、時刻を時間表示したりするにはすこし面倒であるため、プログラミング言語ごとにいくつかの手段が準備されている。Pythonでは、エポックからの秒数をtime.time()関数でfloat型で取得でき、通常は年、月、日、時、分、秒等の単位で情報を保持するtime.struct_time型あるいはdatetime.datetime型で取り扱う。また、ソフトウェアはI/Oの段階では日時の情報は「2018年04月03日(火) 11:00」等の文字列に変換することが多い。日時の書式としてはISO 8601があり、次のように日付と時刻をTで連接して書くが、一般には普及しているとはいいがたい。前者が基本書式で、後者の拡張書式である。UTCのときは最後にZを付け、ほかの時間帯のときは最後に+0900等と書く。

20180403T110000Z
2018-04-03T20:00:00+09:00

ソフトウェア同士のI/OであればISO 8601を強要すればいいが、利用者を考慮すると日常に普及している書式を使う必要があるが、日付の書式は徳に様々である。

2018/04/03
04/03/2018
03/04/2018

と、ISO及び日本、米国、英国で年月日の順番は様々であり、

20180403
2018-04-03
2018/04/03
2018/4/3
2018年4月3日
April 3rd, 2018

等のように区切り文字等も様々で、これに曜日が付いたり、時刻に午前・午後が付いたりと、Excelの値の書式設定でたくさん選択肢がある通りである。もちろんこれら各種の書式に対応すべく、各種の関数が準備されているものの、地域に関しては、時間帯のほかに、これらの自由度というロケールを意識する必要がある。

このように、Pythonスクリプトの中では、日時の情報は以下の4種類のデータ型で保持される可能性がある。

  • 日付を特定の書式で表現したstr型
  • エポックからの経過時間のfloat型
  • Python独自のdatetime型あるいはstruct_time型

すべてに直交性が確保されている訳では無いが、これらを相互に変換する関数が準備されているので、これらのデータ型の特徴を理解し、今どのデータ型で保持しているかを意識するだけで問題は解決するが、困惑の末、奇跡的に動いているスクリプトも多い。

プログラマ等のITエンジニアは、プログラミング言語の文法等のITに関する知識・スキルのほかに、日常の各種の常識・知識を理解する必要がある。特に、今回取り上げた日時の表現と、文字コード等の文字の表現は、これらを最も理解すべきプログラマであっても理解が不足していることが多い。現在のソフトウェアは複数の地域から利用されることを前提にすべきだというにもかかわらず。

PAGE TOP