なにぬねのーつ

No.50 DATEDIFの謎を追え(1) 〜 DATEDIF関数の真実
公開日 2007/12/30 キーワード EXCEL, 1-2-3 対応バージョン 添付ファイル DATEDIF_TESTSET.zip
EXCELには経過年、経過月、経過日を計算するDATEDIFという関数があります。雑誌やWEB等でも紹介されていますのでご存知の方も多いと思います。一様に経過月の計算にバグがあるので使用する際は注意した方がいいとの記述があります。なぜ、バグが存在する関数をマイクロソフトがほっらかしにしておくのでしょう?調べていくとこの関数は非公開関数であること。ロータス1-2-3との互換のために作られた一時しのぎの関数であることがわかりました。普通ならこれであーそうなんだと右から左に受け流してしまうところですが、今回はそうは問屋が卸しませんでした。

DATEDIF関数を使っていくつかテストをしてみましたがバグの全体像がつかめません。EXCELのDATEDIF関数のオリジナルは1-2-3の@DATEDIF関数です。そこで、うずもれたCDの山からスーパーオフィス98を探し出し1-2-3をインストールしてみました。
懐かしい1-2-3の画面
ロータス1-2-3
以下は1-2-3の@DATEDIF関数のヘルプです。日付連番とは1900年から2099年までを整数値化したもののようです。

@DATEDIF
@DATEDIF(開始日,終了日,"処理単位")は、2つの日付連番の間の経過期間を求めます。

引数
開始日 2つの日付のうち始めの方の日付を指定します。1から73050までの日付連番を使います。
終了日 2つの日付のうちあとの方の日付を指定します。開始日と同じかそれより大きい日付連番を使います。
処理単位 経過期間を計算するときの単位を指定します。次の6つのうちのいずれかを使います。"Y"というように両側を二重引用符(" ")で囲みます。

処理単位 計算結果
  Y  年数
  M  月数
  D  日数
  MD  1カ月未満の日数
  YM  1年未満の月数
  YD  1年未満の日数

使用例
1990年2月15日から1993年9月15日までの経過期間を求めます。
@DATEDIF(@DATE(90,2,15),@DATE(93,9,15),"m") → 43
これは、1990年2月15日から1993年9月15日までの月数です。
@DATEDIF(@DATE(90,2,15),@DATE(93,9,15),"md") → 0
開始日と終了日の日の部分が同じなので、結果は0になります。
@DATEDIF(@DATE(90,2,15),@DATE(93,9,15),"ym") → 7
これは、2月から9月までの月数です。

EXCELと1-2-3のテスト結果比較

それではEXCELのDATEDIF関数と1-2-3の@DATEDIFでテストした結果を比較検証していきます。テストには自作のテストセットを使用します。

ケース1)
開始日の日が終了日の日より大きい場合にMDYDの結果がずれています。以下の例では終了日の月が変わったとたんMD,YDの結果が1日飛んでおり明らかにEXCELの誤りといえます。
ケース1
ほとんどの月が間違っています(!)が不思議と合っている月もあるのです。それはたまたま合っているにすぎません。
余談ですがこの誤ったMDの計算は『終了日の月の日数-DAY(開始日)+DAY(終了日)』としているようです。

ケース2)
ところでYDの方ですが、こちらは終了日が2月を越えると(期間内に閏年にかかわらず2月を含むと)すべてNGになります。以下の例では結果が1か月ほど逆戻りしています。こうなると理解の範囲を超えていてどう考えても内部でどう計算しているのかわかりませんでした。
ケース2
ケース3)
さて問題のYM(およびM)です。これまでのMD,YDに関しては周知の事実として知られたバグですが、実はYMにも問題があります。終了日の月の日数が開始日の月の日数より少ない組み合わせで開始日の日が終了日の日より大きくかつ終了日が末日の場合に発生します。終了日の月の日数が開始日の月の日数より少ない組み合わせには1月(29,30,31)〜2月(28)、3月(31)〜4月(30)、5月(31)〜6月(30)、8月(31)〜9月(30)、10月(31)〜11月(30)があります。
ケース3
1/30〜2/28で"1-2-3"のYMの計算は1となっています。終了日の日が開始日の日より少ないのに1月とカウントするのには違和感があります。最初これを見た時は1-2-3の間違いかと思いましたがどうもこれが仕様のようです。なお民法第143条-2に「最後の月に応当する日がないときは、その月の末日に満了する」という記述があるのであながち根拠がないわけでもないようです。

ケース4)
最後にYです。まさか年までずれるとは想定外でした。閏日(2/29)が開始日で終了日が閏年でない2/28の場合に発生します。これはケース3と原理的には同じことです。2/29には4年に1度の閏年にしかありませんから、この結果が正しくないとすると閏日生まれの人は誕生日が無いことになります。法的にも2/28が誕生日となるようです。
ケース4

まとめ

もしあなたがEXCELのDATEDIF関数を使いたいのなら実態を理解することは重要かもしれません。MD,YDオプションはほとんど使い物にならないこと→YM,Mオプションは月末の処理で多少誤差が生じること→Yオプションは閏日(2/29)の処理に問題があることがわかりました。もともと非公開関数ですからバグがあるからと言ってマイクロソフトに文句を言っても始まりません。癖を知って使えばいいのです。

なお上記を含めすべてのテスト結果をEXCELで添付していますので興味のある方はご覧ください。5シート計3000行ほどあります。次のNoでは1-2-3互換のDATEDIF関数のVBA版を公開します。

関連情報:
No.51 DATEDIFの謎を追え(2) 〜 DATEDIF関数の実装(VBA編)
No.52 DATEDIFの謎を追え(3) 〜 DATEDIF関数の実装(ノーツ編)

使用条件・免責事項



[戻る]