投稿

6月, 2023の投稿を表示しています

ClosedXMLで時間値を取得したときの値とEXCELの仕様(特に24時間以上の場合)

イメージ
ClosedXMLで「15:00」のようなセルから、データ値をDateTime型で取得した際の戻り値について。 この記事の内容はClosedXML Ver0.95を対象に書いている。しかしVer0.100で結果が変わったため、誤解の無いように結果のみ先に書いておく。 ・Ver 0.100.0 より前 1899/12/30 HH:mm:ss ・Ver0.100.0 以降 1899/12/31 HH:mm:ss 本文 Excelの時間が入力されたセルから、ClosedXMLで値を取得したとき、TimeSpan型となる場合とDateTime型となる場合がある。これはこれで面倒ではある※が、今回の問題はDateTime型のときだ。 ※ 例えばセルのフォーマットが"[h]:mm:ss"だとTimeSpan型、"[h]:mm"だとDateTime型になったりする Excelでは時刻も日時も内部では同じシリアル値で管理されている。時刻を入力したセルのフォーマットを変更して日付を表示してみると「1900/1/0 ~」と表示される。日付としては不正だが、1日未満という意味で0日なんだろう。 C#のDateTime型では当然0日という日付は表現できない。ではどのような値になるかというと 1899/12/30 ~ そう1899/12/31 ではない のだ。これはExcelの仕様バグに起因する。 1900年2月29日が存在するExcelのバグ 1900年は100の倍数であり400の倍数でないため、本来うるう年ではないのだが、Excelでは仕様バグとして2月29日が存在している。「仕様バグ」と書いたのは、正しくはないが意図的に組み込まれた動作だからだ。 詳しくは以下に公式のアナウンスがある Excel では、1900 年が閏年であると誤って想定されています Windowsが存在する前のソフトとの互換性が、2023年現在でも尾を引いてるというのは面白い。 ちなみにGoogleスプレッドシートでは日時をExcelと同様シリアル値で管理しているが、上記は切り捨てられていて1900年2月29日は存在しない。 ClosedXMLのGetValue ClosedXMLのGetValueでは、DateTime型を生成する際にこの補正などを特にしていないため、1