平成12年12月22日

AccessとVBの日付処理のバグ
(西暦2000年問題)について
兵ちゃんの研究室へ戻る

 マイクロソフト社の製品であるAccessの入力時に2桁で西暦(年)を入力する機能、和暦/西暦変換を自動的に行う機能がありますがその機能よって起こる日付バグの話がありましたので参考に紹介したいと思います。


1 バグの内容
  2001年からは「mm/dd/yy」解釈されて予期しない日付と認識される。フォームで 2004/03/15 とした場合、渡されるときにUS日付の表記とされ、mm/dd/yy  になり日付が間違う現象

 2004/03/15 = 04/03/15 = 戻ってくると 2015/04/03 になる。
  mm/dd/yy

  モジュールに # # で括ったリテラル日付(年2桁で)入れると、2001〜2012年の解釈が違って

  例:  a = #5/9/30#  2005年09月30日ね

      US日付での解釈 mm/dd/yy = 2030年05月09日

  などのUS表記で日付のデ−タを処理するためのエラ−であり、コード中の##で括られている部分全部が対象になります。
  対策としてはコントロールパネルの日付の短い形式を yyyy/mm/dd にする(パソコ ン単体に依存してしまう。)記述を書き換える等の処置が必要になります。
  詳しくは下記の写しを参考にしてください。


2 [ACC2000]yy/mm/dd 日付を#で囲むと"mm/dd/yy"に変換される(写し)
 http://www.asia.microsoft.com/japan/support/kb/articles/J054/8/94.htm

[ACC2000]yy/mm/dd 日付を#で囲むと"mm/dd/yy"に変換される
 最終更新日: 2000/11/29
 文書番号: J054894


この資料は以下の製品について記述したものです。

 Microsoft Access 2000 for Windows (以下 Access 2000)
 Microsoft Access 97 for Windows (以下 Access 97)
 Microsoft Access 95 for Windows (以下 Access 95)

概要
 この資料は "yy/mm/dd" 形式の日付を日付リテラル書式で記述すると、"mm/dd/yy" 形式に変換される現象について説明しています。

現象
 VBA または、クエリーの SQL ビューにて下 2 桁の西暦で日付リテラル書式 (日付を # で囲む 例: #5/10/99#) で入力すると、Jet データベース エンジン (以下 Jet) は自動的に "mm/dd/yy" 形式に変更します。 Jet における日付リテラル書式は "mm/dd/yy" です。この規則は日本語版の Windows において通常設定されている書式 "yy/mm/dd" とは異なります。

状況
 この現象は Jet の仕様による動作です。

回避策
 以下のいずれかの方法で回避できます。

 日付データを扱う場合、Format 関数を使用して日付形式を "mm/dd/yy" に指定する
または西暦 を 2 桁ではなく、4 桁 "yyyy" で扱う


詳細
 「日付リテラル」とは、シャープ記号 (#) で囲まれた有効な形式の文字列のことです。
 「有効な形式」とは、国別情報の設定により指定された日付の書式、または共通日付形式のことです。

 Jet における日付リテラル書式は #mm/dd/yy# です。しかし、この規則で解釈できない日付リテラルはコントロール パネルの日付設定に依存した書式で解釈されます。例えば、日付型の変数に西暦 1999 年 2 月 3 日を設定するつもりで #99/02/03# と入力した場合、Jet は #mm/dd/yy# 形式で解釈します。その結果、西暦 2003 年 99 月 2 日となり、日付として不正なデータとなります。Jet が 99 月を不正なデータと判断した場合、次に、コントロール パネルの日付設定に依存した解釈を試みようとします。
ここで、#yy/mm/dd# としての解釈が成立するため、自動的に日付リテラルを #02/03/99# に変換し、結果的に期待した日付として処理されます。しかし、年を 2 桁で入力した場合、西暦 2001 年から西暦 2012 年の日付が期待通りに解釈されないため問題が発生します。

その他
 Access のクエリーのグリッドが表示する日付は、コントロール パネルの地域設定の短い形式の設定に依存します。

地域設定の短い形式の設定 | 入力した値 | 表示される形式 | Jet に渡される値
----------------------------------------------------------------------------
YY/MM/DD | #2001/02/10# | #01/02/10# | 2001 年 2 月 10 日
YYYY/MM/DD | #01/02/10# | #2001/02/10# | 2001 年 2 月 10 日

 しかし、SQL ビューにて、2001 年 2 月 10 日を設定するつもりで #01/02/10# と入力した場合、Jet の仕様により、"mm/dd/yy" としての解釈が成り立つために、2010 年 1 月 2 日として認識されます。



地域設定の短い形式の設定 | 入力した値 | 表示される形式 | Jet に渡される値
-----------------------------------------------------------------------------
YY/MM/DD | #2001/02/10# | #01/02/10# | 2001 年 2 月 10 日
YY/MM/DD | #01/02/10# | #10/01/02# | 2010 年 1 月 2 日
YYYY/MM/DD | #2001/02/10# | #2001/02/10# | 2001 年 2 月 10 日
YYYY/MM/DD | #01/02/10# | #2010/01/02# | 2010 年 1 月 2 日

3 [VB] 日付リテラルにより日付を設定するときの注意(写し)
 http://www.asia.microsoft.com/japan/support/kb/articles/J047/9/49.htm

[VB] 日付リテラルにより日付を設定するときの注意
 最終更新日: 2000/12/11
 文書番号: J047949

この資料は以下の製品について記述したものです。

 Microsoft(R) Visual Basic(R) 4.0, 5.0, 6.0


現象
 日付リテラルを使用して設定した日付データが期待した日付として保存されていない。

原因
 Visual Basic における日付リテラルの書式は #(Month)/(Day)/(Year)# であり、この規則は既存の Windows 日本語版において通常設定されている書式である (Year)/(Month)/(Day) とは異なります。
この仕様は Visual Basic for Application および VBScript でも同様です。

 たとえば、日付型の変数に西暦 2001 年 2 月 3 日を設定するつもりで #01/02/03# という日付リテラルを代入した場合、西暦 2003 年 1 月 2 日として保存されます。

対策
 日付リテラルの書式を #(Month)/(Day)/(Year)# にするか、年を必ず 4 桁 (YYYY) で指定してください。

詳細
 日付リテラルとは、シャープ記号 (#) で囲まれた有効な形式の文字列のことです。
有効な形式とは、国別情報の設定により指定された日付の書式、または共通日付形式のことです。

 Visual Basic における日付リテラルの書式は #(Month)/(Day)/(Year)# ですが、この規則で解釈できない日付リテラルはロケールに依存した書式での解釈が試みられます。

 たとえば、日付型の変数に西暦 2000 年 2 月 3 日を設定するつもりで #00/02/03# という日付リテラルを代入した場合、#MM/DD/YY# 形式で解釈すると西暦 2003 年 0 月 2 日になり、これは日付としては不正なデータです。
Visual Basic は 0 月を不正なデータと判断した後に、日本語ロケールに依存した解釈を試みます。#YY/MM/DD# としての解釈が成り立つので日付リテラルを自動的に #02/03/00# に変換し、結果的には期待した日付として処理します。

 しかし 01〜12 は年月日いずれとしても解釈可能であるため、年を 2 桁で処理するプログラムでは西暦 2001 年から西暦 2012 年の日付が期待通りには解釈されない問題が生じることがあります。
また、年とは無関係に DD/MM と解釈されることを前提とするコードにおいて 01〜12 が MM/DD として解釈される問題が生じることもあります。

 同様に 13〜31 についても 2 桁年と日のどちらか判断できないような状況は避けなければなりません。

4 その他
  まだ、西暦2000年問題に関連した日付処理のバグ(不具合)があると思われます。
  きおつけましょう。

2000.12.22  兵ちゃん