Q. 日付型ってなんですか?扱いにくいからやめたほうがいいって聞いたんですが…

* Amazon Access VBA 関連書籍情報
もう過ぎ去った感もありますが 2000 年問題。なんでこんな問題が起きたかというと、西暦の上2桁は 19 だという間違った常識がいつのまにかできあがってしまっていたからです。
2020 年現在の時点ではすでに「西暦の上 2 桁は 20」に置き換わってますが、これはこれで難あり。
なぼなんざ、しばらくの間は書類書くとき「2001」と書かなければいけない日付欄に「19」と書いてしまいあわてて修正液を探しておりましたですよ。(間抜け)
まぁ最近は手でモノを書く機会も減りましたので(汗)そういうことはなくなりましたが…
それはコンピュータ業界の話ではなく、一般的な生活の中にも数多くありますよね。
身の回りの品物で日付が刻印されているものは結構あるはずですが、その中で年を4桁で表示しているものがどれだけありますか?
人間が見る分には、「きょうは 1999 年だから 99 年は今年だよね」と頭の中に置き換えルーチンができていて、自分でも知らないうちに判断しているのですが、コンピューターはそうはいきません。
その品物が 100 年たってもまだ現役で使われていたらどうしますか?いつの 99 年だかもうわかりませんよね。
実際は100年以上使うかもしれない品物には年を4桁で表示しますからそんなことはないんですが。
ここに、2000 年問題の原点があります。
つまり、昔のコンピュータ技術者は、みんな「こんなシステム 2000 年まで使わねぇよ」と思っていたのです。(本当)
だから年は2桁で十分だったのです。
これら一連の考え方を根本的に直さないと、2000 年問題の解決はできません。
これから作るシステムは、すべて「年は4桁で表示・入力する」で統一しましょう。昔のデータを貯えるデータベースである以上、この先ずっとついてくる問題です。
Accessのテーブルには「日付型」というデータ型がありますね。正しくは「日付・時刻型」。日付と時刻の情報を1つの領域にもつことができるデータ型です。
昔のCOBOL等で作られたシステムではこのようなデータ型は無かったので、「980518」といった6桁の数字文字で日付を表していました。年2桁、月2桁、日2桁ですね。そもそもこういうデータの持ち方が現在の 2000 年問題を引き起こしているんですが、それはとりあえずおいといて(^_^;)
Access(及び SQL ベースのデータベースエンジン)の日付・時刻型とは、こういったものとは根本的に違います。
内部では「シリアル値」と呼ばれる、一見すると数値にしか見えない値で扱われ、外に見せる時に日付のような表示形式で見せています。その表示形式は場合によって選ぶことができます。
つまり、西暦表示だろうが和暦表示だろうが年4桁だろうが年2桁だろうが思いのままということです。
日付表示形式は、なにも指定されない場合は Windows のコントロールパネルの「地域」内での「日付」設定どおりに表示されます。ちょっと見てみてください。長い形式、短い形式が指定されていますね?
これを状況に応じて表示を変えたい場合は、Format 関数、書式プロパティ等で設定します。
あるクエリーでは西暦2桁表示がしたい、というのであれば Format 関数で編集した結果を表示すればいいし、(書式プロパティでもいいです)あるフォームでは和暦を年号指定して入力、表示したいというのであれば書式プロパティと定型入力を組み合わせて使うことになります。(定型入力は、必ず和暦で入力してもらう等といった規則付けに有効です)
日付・時刻型では日数の計算、月数の計算などの関数が豊富に用意されているので便利ですし、和暦・西暦変換のしくみをVBA、Accessに任せることができます。日付型が現せる範囲は 西暦100年1月1日~西暦9999年12月31日 ですので、2000 年ぐらいでびくびくする必要もありません。
平成が終わって新しい年号が追加された場合、マイクロ●フトの対応を待つしかないのですが、逆に「マイク●ソフトが対応してくれないとダメなんですよーすみませんねー」ととりあえず逃げる、という姑息な手も使えます(^_^;;)(よいSEは真似しないように!)
テーブル上に日付・時刻型でフィールドを作っておくと、SQL 文の中で日付の演算が高速に出来たりというメリットもあります。SQL 文中で型変換関数(cvDate とか?)を使うと処理が遅くなる心配がありますから。
日付・時刻型フィールドにはありえない日付・時刻は入力できませんし、うるう年を含めた日付の論理チェックをプログラム上でやる必要もありません。
では、日付・時刻型を使わないとどうなるでしょう。テキスト型に、19980101 と8桁の数字文字を格納するか、それとも1998/01/01 と入れるか、それとも 平成10年1月1日 と入力するか、月や日が1桁だった場合頭に0を加えるか・・・
あー規則をきめるだけでもうイヤになってしまいますよね。その規則どおりにデータを入力してもらうようにチェックするのもまた大変ですし、かりに和暦を使用するとなると、西暦←→和暦の変換なんてことも考えなければなりません。(まぁこれは型変換関数で日付型へ変換すればいいのですが)
と、いうわけでなぼは、テーブルに日付データを格納する際には日付・時刻型のご使用をお勧めいたします。
ただし、デメリットはまったくない、って訳でもありません、注意する点はもちろんあります。
日付・時刻型では、日付と同時に時刻まで管理できます。なにも考えず日付だけを入力した場合、時刻は午前0時が設定されています。
が、定型入力等で制限を加えていない限り、時刻を入力しようと思えばできてしまうのです。データ入力中なんらかのミスで時刻が入ってしまった場合、画面上で書式を使って日付だけを表示させているとその事実に気づきません。
さらにテーブルのフィールドにある書式プロパティで日付を設定している場合、テーブルをデータシートで開いても入力されている時刻は見えません。コントロールパネルの設定も、通常は時刻が見えない設定になっています。
もし間違って時刻が入力されてしまった場合、1998/09/01 00:00:00 と、1998/09/01 12:31:05 では、比較結果は false(同じではない)になってしまいます。ところが見えているのは日付だけ、両方1998/09/01なのになぜ同じじゃないんだーっっといらんところで悩む羽目になりかねません。
これを防ぐため、フォームなどで日付・時刻型の項目に入力させる場合には定型入力を使うか、時刻が入らないようデータ登録前にチェックする等したほうがいいでしょう。さらに、テーブルの書式プロパティでは年4桁から時刻まですべて表示するよう設定しておいたほうが、テーブルをデータシートで開けば正確なデータ内容をみることができるようになります。
ちょっと追加。たとえ日付・時刻型を採用していたとしても、年の入力は4桁でしなければダメであることだけは忘れないでください。Access は年が2桁で入力された場合、勝手に上2桁を補ってくれますが、その補い方がバージョンや OS や 2000 年パッチが入っているかどうかで違ってくるので注意が必要です。
そんなわけで、なぼはいつも日付データの入力に関しては2桁で入れられようが4桁で入れられようが、入力直後(フォーカス喪失時とか)に必ず年4桁で再表示するようにしています。こうすれば、オペレータさんが間違った入力をする危険性を下げることができます。
さらに追加。モジュール内で日付・時刻型を扱うとき、日付・時刻型の変数どうしでの比較はまるで問題ないですが、日付の入った文字列と比較したり文字列と結合したりするときには、絶対に Format 関数を使い年4桁を明示的に表示するように心がけましょう。こーゆー問題もありますから。コンパネの設定なんかー信じてちゃいけません。頼れるものは己のみ。
さて、「じゃあ、いまテキスト型や数値型で日付データ持ってるんだけど、日付型に変更したい!」場合どうしたらいいか。
*作業前に mdbファイルのバックアップは必ず取りましょう!
手順1:テキスト型以外の項目だった場合、とりあえずテキスト型にする
数値型に日付が入っている場合は、そのまま日付型への変更は難しいので、とりあえずテキスト型に変更しましょう。
もし、倍制度浮動小数点や単制度浮動小数点型であった場合、長整数型にしてからテキスト型に変換したほうがいいかもしれません。
テーブルをデザインビューで開き、データ型のコンボボックスをテキスト型に変更、デザインを保存すればOKです。
インデックスが貼られている場合は、一度インデックスを消してからのほうがいいでしょう。すべての作業が終わってからもう一度インデックスを作成してください。
デザインを保存したら、データシートビューで開いてみましょう。年4桁、月2桁、日2桁、あわせて8桁で日付があらわされていますか?
手順2:データ入力形式を確認
Access が「日付と認識できる」形式できちんとデータが入っている場合、そのまま日付型に変換できる場合もあります。たとえば、
◎ 1998/04/01 たいへんよろしい
○ 98/04/01 1900年になるか2000年になるか、年によって違っちゃうので注意が必要
○ 平成10年4月1日 大丈夫。
○ H10/4/1 これもOK。
× 980401 残念ながらダメ(T-T)
× 19980401 これもダメ(T-T)
× H100401 あーこれもダメー
× 98.04.01 これもダメ・・
Access が「日付だっ」と認識するためには、「区切り記号」が必要なのです。コントロールパネルの「地域」-「日付」で定義された区切り文字(通常、日付は「/」、時刻は「:」ですね)のほかに、年、月、日といった文字も区切り文字としてみとめてくれています。
和暦を入力する場合、「平成」「昭和」といった漢字、H、S、M 「平」「昭」といった略称(?)もOkのようです。(書式プロパティで現せるものは使えるようです)ただ、平成は4、昭和は3 といったコードとは対応づけしてくれないので、(当然)そのようなデータの場合はあらかじめ4を「平成」などのAccess が認識できる和暦文字に置き換えておく必要があります。
この規則どおりのデータなら問題はないので、そのまま手順4:データ型を変更 に進んでください。
手順3:日付に変換できる形式にデータを変更する
手順2で確認した結果、「このままじゃ日付型に変換できない!」とわかった場合、なんとかデータを日付型に変換できる形式に変更しなければなりません。10~20件程度なら手で修正したってたいしたことはないですが、Accessはデータベースソフト、その程度の件数であるとは限りませんよね。
大量データの更新には、たいていの場合「更新クエリー」を使います。
*[年月日]という項目に以下のようなデータが入っている場合*
- 980401 の場合
Left([年月日],2) & “/” & Mid([年月日],3,2) & “/” & Right([年月日],2)
または Format$([年月日],”@@/@@/@@”) - 19980401 の場合
Left([年月日],4) & “/” & Mid([年月日],5,2) & “/” & Right([年月日],2)
または Format$([年月日],”@@@@/@@/@@”) - H100401 の場合
Left([年月日],3) & “/” & Mid([年月日],4,2) & “/” & Right([年月日],2)
または Format$([年月日],”@@@/@@/@@”) - 98.04.01 の場合
Left([年月日],2) & “/” & Mid([年月日],4,2) & “/” & Right([年月日],2)
ご助言をいただいた アスタロート様、ありがとうございました。
このような式を使って変換した結果を、更新クエリーを使って更新してしまいます。
クエリーデザインビューでメニューバーから[クエリー]-[更新] を選ぶとクエリーは「更新クエリー」になりますので、その後「レコードの更新」部に上記の式を記述します。更新クエリーの作り方についてはHelpを参照してください。
手順4:データ型を変更する
データベースウインドウから、データ型を変更するテーブルをデザインのみコピーしてとりあえず別の名前をつけておきます。このテーブルをデザインビューで開き、データ型を日付・時刻型に変更し、デザインを保存します。
次にコピー元のテーブルから追加クエリーで新しいテーブルにデータを追加します。追加する時にエラーが出た場合、手順3でデータ形式を変更しきれなかったと思われます。Accessが日付型に変換できないデータが残っていたのです。
追加できなかったデータは不一致クエリー(ウィザードで作れます)で探せますので、データを訂正して再度追加、エラーがなくなるまで繰り返します。
Access に限らず、SQL データベースを扱う場合は日付・時刻型と無縁でいることはできませんので、これを上手に使いこなせるように頑張りましょう。特性さえ知ってしまえば、こんなに便利なものはありませんよ。
ただし、前述のとおり、いくら日付・時刻型を使っても Micr○soft から提供されるパッチをあてても、年を2桁入力する限り2000年問題の解決はできませんのでご注意を。