tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^5: 日付関数DateValueについて
投稿日: 2011/01/09(Sun) 14:14
投稿者魔界の仮面弁士
VB2〜VB6 の日付値(≠日付型)が用いる日付シリアルは「OLE オートメーション」で
使われる物であり、OADate とも呼ばれる実装です。これは表計算ソフトのそれとは異なり
「1899/12/30 からの経過日数」として算出されています。シリアル値でみると、

 1899/12/30         =>    0.0
 1899/12/31         =>    1.0
 1900/01/01         =>    2.0

という実装になっています。
整数部で日付を管理し、小数部(の絶対値)で時刻を管理しています。
1900年3月以降の日付においては、表計算ソフトの日付シリアルと同じ値なので
都合が良かったわけですね。(No.15075 でも解説されていますね)



> 天文の問題に興味が移り、その中にシリアス値とかユリウス日とか
(中略)
> VB6では1900年が閏年と判断しない重大なバグあることでした。
もしかしてユリウス暦と混同されていないでしょうか。

1900年は、ユリウス暦では閏年に当たりますがグレゴリオ暦では平年です。
VB6の標準カレンダーはグレゴリオ暦なので、VB6の実装は間違っていません。
(既に No.15077 でも解説されていますけれどね)

一方、Excel の日付シリアル実装がバグっているかというと、これも微妙な所があります。

かつて Lotus 社の「1-2-3」という当時トップシェアを誇る表計算ソフトにおいては、
シリアル値 0 を 1900/01/00 としていましたし、また、1900/02/29 という
本来は存在しない日付が扱われていました。

もちろん、1900/01/00 や 1900/02/29 が、正しい日付ではありませんから、
ある意味ではバグと言えます。

しかしこれは、当時の低性能コンピュータでは、メモリ効率や処理速度を優先するが故に、
実装をできる限り単純化して実装していたという事情が要因としてあります。
(1900年や2100年という日付が必要になるケースは稀ですので)

# その実装の是非については、後の Y2K 問題にも絡んでくることになるのですが、
# それはまた別の話として…。

かといって、後継バージョンでこの仕様を改めてしまうと、日付データに
ズレが生じるため、互換性という観点で問題があります。そのため、Excel などの
他社製品においては、その日付実装を「あえて」採用しているわけです。

ゆえに現行の表計算ソフトにおいては、この実装方法はバグであるというよりも、
過去の(限定的な)実装をあえて踏襲したわけで、その意味では「仕様」と言えます。
(そもそも、Excel で扱える日付範囲は、VB が扱える日付範囲よりも少ないです)


ただし Excel に話を限定したとしても、
> 事の発端は「シリアル値を求める」ことで、「シリアル値とは1900年1月1日を1とし、
という表現は(間違いではないにしても)、必ずしも正確では無かったりします。

なぜならば「シリアル値 0 を 1904/01/01 とするモード」も存在するからです。
http://support.microsoft.com/kb/214330/ja
http://developer.apple.com/jp/qa/ops/ops23.html


> 天文の問題に興味が移り、その中にシリアス値とかユリウス日とか
> 日数計算が必要になりました。
Visual Basic においては(VB6 も VBA も含めて)、日付は基本的に
グレゴリオ暦が採用されていますが、実は回教暦も使えるようになっています。

「Calendar =vbCalHijri」を実行することで回教暦に切り替わり、
グレゴリオ暦に戻すには「Calendar = vbCalGreg」を実行すれば OK です。
(回教暦/ヒジュラ暦は、日本ではイスラム暦と呼ばれる事も多いですね)

なので、
 Calendar = vbCalHijri
 Debug.Print IsDate("2000/02/30")    'True
 Debug.Print IsDate("2000/03/31")    'False
 Calendar = vbCalGreg
 Debug.Print IsDate("2000/02/30")    'False
 Debug.Print IsDate("2000/03/31")    'True
という結果になったりします。


回教暦は太陰暦の一種です。
西暦とは異なり、一か月は 29日 or 30日であり、一年は354日です。
また、日本の旧暦とは異なり、閏月や閏年といった補正も行われません。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。