[833] たまにはエクセルでも 投稿者:ぽう 投稿日:2001/10/24(Wed)

土日にやっていたのが DATEDIF の謎に迫る! ということで
"YD" と "MD" の仕様を調べていました。
もう何年も前に考えて、わからずじまいになっていました。
"MD" の方はこんな計算の結果と一致するようです。

Function DateDif_MD(Date1, Date2)
  If Day(Date2) >= Day(Date1) Then
    DateDif_MD = Day(Date2) - Day(Date1)
  Else
    DateDif_MD = Date2 - DateSerial(Year(Date2), Month(Date2) - 1, Day(Date1))
  End If
End Function

"YD" がわかりません。閏年と、開始日と終了日の日(yyyy/m/d の d) の
大小関係が、ずれに影響しているようなのですが。
(1)日だけ独立して計算している部分がある
(2)他の日付関数を呼び出している部分がある
(3)その他
という可能性を考えています。
とりあえず DATEDIF(,"YD") の結果と一致するように場合分けをしていったら
長大なコードになってしまいました。
今回も迷宮入りか… 重要な話ではないですが。(^_^;)

[833へのレス]Re: たまにはエクセルでも 投稿者:SIMO 投稿日:2001/10/24(Wed)

皆さん、はじめまして。SIMOです。ここでは初めての発言です。
ぽうさん、先日はお世話になりました。

懐かしい話題に釣られて出てきました。

>>"YD" がわかりません。閏年と、開始日と終了日の日(yyyy/m/d の d)
>>の大小関係が、ずれに影響しているようなのですが。

お宝リストに載せてあるのを書いた時に、この二つを集中して調べました。
あの年のF1に行ったときに、名古屋のホテルで、リブレットとにらめっこ
していたのを思い出しました。

お宝リストには、(気が弱いもんで(^^;;)はっきり書けなかったのですが、
"YD"は、はっきりバグですね。付け焼き刃で処理したのが見え見えです。

[833へのレス]Re: たまにはエクセルでも 投稿者:ぽう 投稿日:2001/10/24(Thu)

SIMO さんへ

WORLD PC EXPO ではお世話になりました。
せっかく来ていただいたので、長大なコードというのをご紹介しますね。
眉間に皺の跡がしのばれる作品となっております。(^_^;)

Function DateDif_YD(Date1 As Date, Date2 As Date) As Long
  Dim d2 As Date
  Dim md1 As Long
  Dim md2 As Long
  Dim x As Long
  md1 = Month(Date1) * 100 + Day(Date1)
  md2 = Month(Date2) * 100 + Day(Date2)

  If md1 <= md2 Then
    d2 = DateSerial(Year(Date1), Month(Date2), Day(Date2))
  Else
    d2 = DateSerial(Year(Date1) + 1, Month(Date2), Day(Date2))
  End If

  If Day(Date1) > Day(d2) Then

    If IsLeap(Date2) And (Month(Date2) >= 3) Then
      x = x + 1
    End If

    If IsLeap(Date1) Then
      If (Month(Date1) >= 3) Then
        x = x + 1
      End If
      If (md1 > md2) Then
        x = x - 1
      End If
      If IsLeap(Date2) And (Month(Date1) <= 2) And (Month(Date2) <= 2) Then
        x = x + 1
      End If
      If (Month(Date1) = 1) And (Month(Date2) = 2) Then
        x = x - 1
      End If
    End If
    If IsLeap(Date2) And (Month(Date2) >= 4) Then
      x = x - 1
      If IsLeap(Date1) And (Month(Date1) <= 2) Then
        x = x + 1
      End If
    End If

    If IsLeap(Date1) And (Not IsLeap(Date2)) Then
      If (Month(Date1) <= 2) Then
        x = x + 1
      End If
      If ((Month(Date2) = 3) Or (Month(Date2) = 1)) And (md1 <= md2) Then
        x = x - 1
      End If
    End If

    If IsLeap(d2) Then
      If (Month(Date2) = 3) Then
        x = x - 1
      End If
      If (Month(Date2) >= 4) And (md1 <= md2) Then
        x = x - 1
      End If
    End If
  End If

  DateDif_YD = d2 - Date1 + x
End Function

Function IsLeap(Date1 As Date) As Boolean
  IsLeap = Month(DateSerial(Year(Date1), 2, 29)) = 2
End Function

こんな複雑なことをやっているわけはないですね。

[833へのレス] Re: たまにはエクセルでも 投稿者:角田 投稿日:2001/10/25(Thu)

こんにちは。興味深い話題ですね。

[YD]の結果を眺めてたら面白い規則性があるようですね。

平年→閏年の場合に
2001/1/1 〜 2004/2/28 → 58
      2004/2/29 → 59
      2004/3/ 1 → 59
      2004/3/ 2 → 60
となるんですが、この「58・59・59・60」という
パターンが終了日の2月末日位置固定ではなく、開始日の
「日」に合わせて、このパターンを維持したままシフトして
いくんですね。
[2001/1/2〜]にすると[2004/2/29,3/1,3/2,3/3]
[2001/1/3〜]にすると[2004/3/1,3/2,3/3,3/4]
[2001/1/4〜]にすると[2004/3/2,3/3,3/4,3/5]
ただし、開始日の「月」が変わると、また元の位置に戻って
2001/2/1 〜 2004/2/28 → 28
      2004/2/29 → 29
      2004/3/ 1 → 29
      2004/3/ 2 → 30

2001/4/1 〜 2004/2/28 → 333
      2004/2/29 → 334
      2004/3/ 1 → 334
      2004/3/ 2 → 335
からスタートしていきます(3月の場合には現れませんね)。
逆に閏年→平年だと
2000/1/1 〜 2005/2/28 → 58
      2005/3/ 1 → 60
      2005/3/ 2 → 61

2000/2/1 〜 2005/2/28 → 27
      2005/3/ 1 → 29
      2005/3/ 2 → 30
という風に[59・28が抜けた]パターンが同じ様にシフトして行きます
(こちらは3月以降は現れません)。
閏年→閏年や平年→平年では全く現れないですね。

『2月末日位置固定ではなく、開始日の「日」に合わせて、
 このパターンを維持したままシフトしていく     』
というのがポイントじゃ〜ないかと見てますが‥‥‥
2001/1/2 〜 2004/2/28 → 57
      2004/2/29 → 58
      2004/3/ 1 → 58
      2004/3/ 2 → 59
という風に「日数が減って、同じ日付位置(2/29,3/1)でダブる」
ならば単に月末処理の不具合だけでしょうけど、実際は
2001/1/2 〜 2004/2/29 → 58
      2004/3/ 1 → 59
      2004/3/ 2 → 59
      2004/3/ 3 → 60
という風に「同じ日数位置でダブる」という事は『終了日』を
『開始日の日』だけ前シフトさせて『1日〜』という計算に換算
しているのではないか、とも考えられないでしょうか‥‥‥
 

[833へのレス] Re: たまにはエクセルでも 投稿者:ぽう 投稿日:2001/10/25(Thu)

角田 さんへ

>という風に「同じ日数位置でダブる」という事は『終了日』を
>『開始日の日』だけ前シフトさせて『1日〜』という計算に換算
>しているのではないか、とも考えられないでしょうか‥‥‥

ありがとうございます。(^_^)
そうか〜 開始日の日だけシフトして、それから差の計算ですね。

Function MyDateDifYD(Date1 As Date, Date2 As Date) As Long
  Dim d1 As Date
  Dim d2 As Date
  d1 = Date1 - Day(Date1) + 1
  d2 = Date2 - Day(Date1) + 1
  If Month(d1) <= Month(d2) Then
    MyDateDifYD = DateSerial(Year(d1), Month(d2), Day(d2)) - d1
  Else
    MyDateDifYD = DateSerial(Year(d1) + 1, Month(d2), Day(d2)) - d1
  End If
End Function

2000年付近のデータで試してみましたが、結果は一致するようです。
もしもこの計算方法だとしたら、Month(d1) <= Month(d2) の比較のために
開始日を1日にしたのでしょうか… (^_^;)
 

SIMO さんへ

>涙無しには見れませんね、長大コード。(^^;;;
>プリントアウトして、じっくり見ているんですが、未だに何やってるのかよくわか
りません。

DATEDIF の結果と差が出たらそれを打ち消すためのコードを書き加えて
行っただけで、私にもどういう意味があるのかはわかっていません。(^_^;;
 

>R5Jでは、不具合はありませんでした。

ありがとうございます。そうですよね… 別段、難しい計算でもないですし、
普通に計算すればいいのに、本当にどうしてなんでしょうね >Excel