[FIG(pull-quote)[

>1万年と2千年前から愛してる

[FIGCAPTION[
[CITE[創聖のアクエリオン]]
]FIGCAPTION]
]FIG]


[11] [DFN[西暦1万年問題]]は、4桁[[以下]]で[[西暦年]]を扱うシステムにおいて、
[TIME[西暦10000年][10000]][[以上]]の[[日時]]を扱えないという[[桁溢れ問題]]です。

[12] [[2桁で年を扱う][2桁年号]]システムに関する[[西暦2000年問題]]のついでに注目され、
一部で対策が行われましたが、完全解決には至っていません。

[19] はるか先の[[日付]]であり、[[将来の日時]]として取り扱うことすらほとんどないため、
あまり真剣には取り組まれていません。

[21] 
[[年問題]]の本質とは何かを考えさせられます。
[SEE[ [[年問題]] ]]

* 対処済みの日時形式

[6] [[ISO 8601]] は、 (4桁の構文の自然な拡張では''ない'') [[展開表現]]により[[1万年問題]]に対処しています。

[7] [CODE[xs:dateTime]] は[[展開表現]]ではなく既存の構文の自然な拡張によって[[1万年問題]]に対処しています。
(意図的かどうかは書かれていませんが) [[ISO 8601]] に違反しますが、
[[XML Schema]] は [[ISO 8601]] を[[規定]]ではなく[[参考]]として参照しているので、
構わないと考えているのでしょう。

[8] [[ISO 8601]] から派生した独自の構文である[[HTMLの日時形式]]は、
[[展開表現]]ではなく既存の構文の自然な拡張によって[[1万年問題]]に対処しています。

-*-*-

[22] 
[CITE[MEW3 PktCDateLib]], [TIME[2021-05-24T08:18:39.000Z]], [TIME[2000-12-02T20:56:12.909Z]] <https://web.archive.org/web/20001202204800/http://www3.gamewood.net/mew3/pilot/pocketc/pktcdate/index.html>

[23] この [[PktCDateLib]] という [[Palm OS]] 用の[[ライブラリー]]は
[[RFC 2550]]
が[[西暦1万年問題]]に対処する従来手法の唯一知られる例として引いていました。
[SRC[>>4]]

[24] この[[ライブラリー]]は
「YYYYMMDD」
式の[[日付形式]]を採用していました。 [SRC[>>22]]

[25] 
この方式の (「DDMMYYYY」のような他の方式に対する) 利点として、
そのままの大小が[[日]]の大小になることと、
[[年]]を5桁に拡張して[[西暦1万年問題]]対策とできることが挙げられていました。
[SRC[>>22]]

;; [27] 
[[年月日]]順が普通の[[日本]]で生活していると考えにくいですが、
欧米人にとって[[年月日]]をこの順序で並べるだけのことにも理由をわざわざ書く必要があったようです。

[26] 
ただし本ソフトウェアは
[[old Palm epoch]]
を使っていたので、
西暦2031年までしか扱えませんでした。
[SRC[>>22]]

[28] 
当然ながら5桁に拡張しても99999年までしか記述できません。
次は6桁に拡張する必要が出てきます。

* RFC 2550 の日時形式

[5] [TIME[1999-04-01]]に[[出版]]された[[4月1日のRFC]]である [DFN[RFC 2550]]
は、[[インターネット]]における[[1万年問題]]を扱っており、
[[1万年問題]]を解決した[DFN[RFC 2550の日時形式]]を定義しています。

[REFS[
- [4] [CITE@en[[[RFC 2550]] - Y10K and Beyond]] ([TIME[2017-03-19 16:23:49 +09:00]]) <https://tools.ietf.org/html/rfc2550>
]REFS]

[13] 単に[[年]]の桁数を増やすだけでなく、
[[ASCII]] 順での[[整列]]が[[日時]]の[[整列]]となることを重視しています。

[14] [[紀元前]]にも対応しています。

[15] [[年]]のみならず、[[月]]まで、[[日]]まで、[[時]]まで、
[[分]]まで、[[秒]]まで、任意の桁数の[[秒の小数部]]までと任意の精度の[[日時]]を表現できます。
粗い[[日時]]と細かい[[日時]]が混在する場合の[[整列]]は、
[[ASCII文字列]]の[[整列]]と同様に、粗い[[日時]]が細かい[[日時]]の最初の瞬間の前に来ます。

[16] 区切りの記号を使わず、[[年]]と[[秒の小数部]]以外は固定の桁数の
[[ASCII数字]]列となっています。どの部分も最大値の規定はなく、
実在する[[日時]]の最大値を超えた時は、次の存在する[[日時]]の直前の瞬間を表すことになっています。
(例えば [CODE[A999991232]] (12月32日) は [CODE[B100000]] の前の瞬間を表しています。)


-*-*-

[36] 
[[Y10K date]]
は
[[TAI]]
の[[日時]]を表します。
[SRC[>>4]]

[31] 
[[Y10K date]] 
構文は無限の[[過去][過去の日時]]から無限の[[未来][未来の日時]]まで記述できますが、
[[実装]]は[[宇宙]]の寿命を考慮した限界を設けて構わないとされています。すなわち、
[SRC[>>4]]

- [32] 
[[Y10K compliant program]]
は、
[[宇宙]]の想定される寿命に整合する形で対応する[[日付]]の範囲を制限して[MAY[構いません]]。
- [34] 
[[Y10K compliant system]]
は、
最低、
過去および未来に 10[SUP[29]] 年間の[[日付]]を[[受理]]する[SHOULD[べきです]]。
- [33] 
[[Y10K compliant system]]
は、
過去 10[SUP[12]] 年間、
未来 10[SUP[20]] 年間の
[[Y10K date]]
を[[受理]]しなければ[MUST[なりません]]。

[35] 
[[宇宙論]]の研究の進展でこのへんの規定は改訂する必要があるかもしれませんね?

-*-*-

[37] 
[[Y10K date]]
は[[印字可能ASCII文字]]の列です。
[SRC[>>4]]

[38] 
[[Y10K date]] 
は、
[[Y10K year]]
の後に年内の日時を続けたものです。
[SRC[>>4]]

-*-*-

[43] 
[DFN[Y10K year]] は、
[[年]]番号によって記述方法が違います。
[SRC[>>4]]

- [56] [N[1]] 年とそれ以後は、次のように記述します。
-- [44] 
[ [N[1]], [N[999]] ]
は、[[0埋め]]して4桁の[[10進数]]の[[ASCII数字]]列で表します。
-- [45] 
[ [N[1000]], [N[9999]] ]
は、そのまま4桁の[[10進数]]の[[ASCII数字]]列で表します。
-- [46] [N[10000]] [[以上]]の[[年]]は、
[[ASCII数字]]列の前に、
その桁数で決まる記号を付けます。
- [68] [N[1]] 年よりも前は、[[西暦紀元前]]の[[年]]を変換して記述します (>>69)。


;; [52] 仕様書は4桁の時以外、
[[ASCII数字]]列は[[10進数]]だと明記していません。

[47] 
[[年]]が [N[10000]] [[以上]]の[[年]]は、
[CODE[A10000]],
...,
[CODE[Z999999999999999999999999999999]],
[CODE[^A1000000000000000000000000000000]],
...,
[CODE[^Z99999999999999999999999999999999999999999999999999999999]],
...,
[CODE[^^AA100000000000000000000000000000000000000000000000000000000]],
...
と表します。
[SRC[>>4]]
この先頭にある桁数を表す記号列は、
[[ASCII文字列]]としての[[比較]]と[[年]]の大小が一致するように決められています。

[48] 
先頭の記号列は、0個[[以上]]の [CODE[^]] の後に、
1個[[以上]]の [[ASCII大文字]]を続けたものです。
[SRC[>>4]]

[FIG(railroad)[
= *
== [CODE[^]]
= +
== [[ASCII大文字]]
]FIG]

[64] 
ただし
[CODE[^]] 
と
[[ASCII大文字]]の数には制約があります。
[SRC[>>4]]

- [65] [VAR[n]] : [CODE[^]] の数
- [66] [VAR[m]] : [[ASCII大文字]]の数
- [67] [VAR[m]] = fib([VAR[n]])
- [55] fig([VAR[n]]) : 標準[[フィボナッチ数列]]
-- fib(0) = 1
-- fib(1) = 1
-- fib([VAR[n]] + 2) = fib([VAR[n]]) + fib([VAR[n]] + 1)


[53] 
先頭の記号列から[[年]]の桁数は次のように決まります。
[SRC[>>4]]

- [54] [VAR[年の桁数]] = base26([VAR[ASCII大文字列]]) + y10k([VAR[n]])
- [57] base26([VAR[文字列]]) : [[ASCII大文字]]で表される[[26進数]]
-- [58] base26([VAR[文字]]) = ASCII([VAR[文字]]) - ASCII([CODE[A]])
--- [59] ASCII([VAR[文字]]) : [VAR[文字]]の [[ASCII]] [[符号位置]]
-- [60] base26([VAR[文字列]] [VAR[文字]]) = 26 × base26([VAR[文字列]]) + base26([VAR[文字]])
- [61] y10k([VAR[n]])
-- [62] y10k(0) = 5
-- [63] y10k([VAR[n]] + 1) = 26[SUP[fib([VAR[n]])]] + y10k([VAR[n]])

[69] 
[N[1]] 年よりも前の[[年]]は、次の手順の結果で表します。
[SRC[>>4]]

[FIG(steps)[
= [70] [VAR[y]] を、[[B.C.E.]] の年番号に設定します。
= [71] [VAR[s]] を、 [VAR[y]] 年の [[Y10K year]] に設定します。
= [72] [VAR[s]] の [[ASCII大文字]]を、すべて[[26進数]]の[[補数]]に置き換えます。
-- [73] 例えば A → Z、B → Y
= [74] [VAR[s]] の[[ASCII数字]]を、すべて[[10進数]]の[[補数]]に置き換えます。
-- [75] 例えば 0 → 9、1 → 8
= [76] [VAR[s]] の [CODE[^]] を、すべて [CODE[!]] で置き換えます。
= [77] [VAR[s]] が4桁の[[ASCII数字]]列の場合、先頭に [CODE[/]] を付けます。
= [78] [VAR[s]] の先頭が [CODE[!]] か [CODE[/]] でない場合、
先頭に [CODE[s]] を付けます。
= [79] [VAR[s]] を返します。

]FIG]

;; [85] 
この仕組みは[[補数]]を使うため[[人間]]の直感的な読解が困難です。
[[日時の比較]]と[[文字列の比較]]を一致させるためこのような方式を採用しています。
過去の日時よりも今後の日時の方が多いのだから、
この程度の不便は許容できるとされています [SRC[>>4]]。

[84] 
[[年]]の桁数はこのように定められていますが、それに満たなくても妥当な
[[Y10K date]]
ではあるとされます。末尾に [CODE[0]]
を書き足したものと同じ[[日付]]を表すとされます。
例えば
[CODE[A1]]
は
[CODE[A10000]]
と同じで1万年を表します。
[SRC[>>4]]




-*-*-

[80] 
年内の日時は、
任意個の[[ASCII数字]]を続けたものです。
先頭から順に、
[[月]]、[[日]]、[[時]]、[[分]]、[[秒]]、[[ミリ秒]]、[[マイクロ秒]]、
[[ナノ秒]]、[[ピコ秒]]、[[フェムト秒]]とどんどん細かい単位を表していきます。
[SRC[>>4]]

[50] 
[[月]]から[[秒]]までは、
それぞれ2桁で表します。
[SRC[>>4]]

[51] 仕様書上明記されていませんが、
すべて[[10進数]]で表したものです。
1桁の数値は[[0埋め]]します。

[39] 
[[月]]から[[秒]]までの数値には[[値域]]の制限がなく、 
[CODE[00]]
から
[CODE[99]]
まですべてが構文上認められています [SRC[>>4]]。

[81] 例えば
[CODE[A99999]] 
の最後の瞬間と
[CODE[B100000]]
の最初の瞬間の間に
[CODE[A999991232]]
が入ると例示されています [SRC[>>4]]。

;; [82] これが現実世界の[[時間軸]]で何に当たるものか不明ですが...

[83] 構文上は2桁単位での指定が義務付けられているのですが、
規定本文ではそうでもないようなことが書かれていて、
実際上1桁だけ書いた例も示されています。
例えば
[CODE[A999992]]
は
[CODE[A9999920]]
(99999年20月)
を表します。
[SRC[>>4]]



-*-*-

[40] 
[[日時の比較]]では、
[[部分文字列]]になる[[日付]]はより小さいとします。
[SRC[>>4]]

[EG[
[41] 例えば
[CODE[19990401000000]] < [CODE[19990401000000000]]
[SRC[>>4]]
]EG]

[49] 
その他は[[ASCII文字列]]の[[比較]]が[[日時の比較]]と一致します。


-*-*-

[17] [[4月1日に発行された RFC][4月1日のRFC]] であり、
検討するのも野暮な話かもしれませんが、
現実的にはあまり使い勝手の良い[[日時形式]]ではないかもしれません。
([[RFC 2550]] はいい性質を供えたよい方式だと謳っていますがねw)

[18] [[文字列]]としての[[整列]]を重視する余り、[[可読性]]を著しく落としていますし、
1万年以上で使われる英字や記号は人間が扱うには難しすぎる (ミスする可能性が高い) ものです。
[[整数時刻系]]などの完全に機械処理向けの[[日時形式]]を使わず、
[[人間]]向けの[[年]][[月]][[日]]の構造を残した[[日時形式]]を敢えて採用する場面では、
こうした欠点は致命的です。

-*-*-

[42] 
[[西暦年]]や[[グレゴリオ暦]]、[[24時間制]]が暗黙の前提となっています。
それ以外の[[紀年法]]や[[暦法]]や[[時法]]には対応していません。

[86] 
[[RFC 2550]]
は、
未解決の課題として、
Aztec, Bhuddist, Jewish,
Muslim, and Hittite calendars
の[[日付]]など異なる [[calendar system]]
の[[日付]]は直接は比較できない、
まず common calendar に変換しなければならない、
と述べていました。
[SRC[>>4]]

[87] 
どうやら著者らは[[グレゴリオ暦]]等以外の[[日付]]の記述には使えるが、
[[比較]]には支障があると認識していたようです。
実際には問題はそう単純ではありません。例えば[[閏月]]の[[月名]]は整数化できませんし、
[[元号]]や[[チベット暦]]の年数も整数化できません。

[88] 
[[RFC 2550]]
は、
将来[[年]]の re-numbering があると対応できない、
新たな 「Year 0」 が出現して常用に供されると古い[[日付]]は調整しなければならなくなる、
[SRC[>>4]]
としていました。

[89] 
つまり将来の[[改元]]の可能性は視野に入れつつ
(ただし東洋式の[[元年]]ではなく[[0年]]から起算)、
その場合に構文はそのままで[[元期]]を変えるという構想だったようです。

[90] 
更には、
[[年]]や[[日]]などが[[地球]]中心で将来の[[太陽系]]の終焉後に問題となり得ること、
将来の[[惑星]]間、[[銀河]]間の時刻同期手法の合意が未形成であること、
[[宇宙]]の終焉後の[[日付]]のゆくえが不透明であることが、
課題として指摘されていました。
[SRC[>>4]]


* 未対応の日時形式

[10] [[RFC 3339の日時形式]]は4桁固定で、[[西暦1万年問題]]未対応です。

[29] [[インターネットメールの日時形式]]は4桁[[以下]]で、[[西暦1万年問題]]未対応です。

[92] [[Microsoft Excel]] [SEE[ [[1900 date system]], [[1904 date system]] ]]

* 関連

[9] [[将来の日時]]も参照。

* メモ

[1]
[CITE@ja[西暦10000年問題 - Wikipedia]] ([TIME[2007-01-10 09:55:23 +09:00]] 版) <http://ja.wikipedia.org/wiki/%E8%A5%BF%E6%9A%A610000%E5%B9%B4%E5%95%8F%E9%A1%8C>
([[名無しさん]])

[2]
[CITE@en[Year 10,000 problem - Wikipedia, the free encyclopedia]] ([TIME[2007-01-17 09:39:58 +09:00]] 版) <http://en.wikipedia.org/wiki/Year_10%2C000_problem>
([[名無しさん]])


[3]
一万年問題のポイントの1つは、そんな先のことまで考えずとも、
もっと若い[[年号]]すらまともに扱えない (のがほとんどである)
ことではありますまいか。 

[30] [CITE@ja-jp[10000年問題 ‐ 通信用語の基礎知識]], [TIME[2021-05-24T08:36:52.000Z]] <https://www.wdic.org/w/TECH/10000%E5%B9%B4%E5%95%8F%E9%A1%8C>

[20] [CITE@ja-jp[9340年問題 ‐ 通信用語の基礎知識]]
([TIME[2018-04-24 00:01:08 +09:00]])
<http://www.wdic.org/w/TECH/9340%E5%B9%B4%E5%95%8F%E9%A1%8C>

[91] [CITE@ja[西暦10000年問題 - アンサイクロペディア]]
([TIME[2023-07-11T21:45:44.000Z]], [TIME[2023-08-09T02:06:22.024Z]])
<https://ja.uncyclopedia.info/wiki/%E8%A5%BF%E6%9A%A610000%E5%B9%B4%E5%95%8F%E9%A1%8C>