System.DateUtils.MonthsBetweenの不思議な挙動について

Embarcadero Quality PortalのRSP-11694より。

System.DateUtils.MonthsBetween関数は、指定した2つのTDateTime値の間隔が何か月かを返します。

次のコードを実行すると、

uses
  System.DateUtils,
  System.SysUtils;

begin
  WriteLn(MonthsBetween(EncodeDate(2015, 8, 1), EncodeDate(2015, 8, 31)));
  WriteLn(MonthsBetween(EncodeDate(2015, 7, 1), EncodeDate(2015, 8, 31)));
  WriteLn(MonthsBetween(EncodeDate(2015, 6, 1), EncodeDate(2015, 8, 31)));
  WriteLn(MonthsBetween(EncodeDate(2015, 5, 1), EncodeDate(2015, 8, 31)));
  WriteLn(MonthsBetween(EncodeDate(2015, 4, 1), EncodeDate(2015, 8, 31)));
  WriteLn(MonthsBetween(EncodeDate(2015, 3, 1), EncodeDate(2015, 8, 31)));
end.

実行結果はこのようになります。

0
2
2
4
4
6

納得できない結果ですね。

ちなみにExcelのDATEDIF関数(=DATEDIF(A1, B1, “m”))を使うと、こうなります。

2015/8/1 2015/8/31 0
2015/7/1 2015/8/31 1
2015/6/1 2015/8/31 2
2015/5/1 2015/8/31 3
2015/4/1 2015/8/31 4

コメント

  1. リンクされたヘルプに以下の記載があります。

    >MonthsBetween は「1 か月=30.4375 日」という想定を基に、近似値を返します。

    月によって30日、31日の違いを考慮されていないので、返り値がおかしなものになっているようです。

  2. 安易な実装のように思えますが、歴史的経緯があるのかもしれません。
    Excelのような賢い関数がDelphiにも欲しいと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください