日付・時刻を取得するときの落とし穴


先日メールで「Date関数の返り値がおかしい」という質問を受けて思い出しました。今回は"役立つテクニック"ではなく、Windowsの設定によって関数の返り値が変わるという"落とし穴"の話です。

VBAで現在の日付を調べるときはDate関数を使います。現在の時刻ならTime関数、日付と時刻を両方同時に調べたいときはNow関数を使います。けっこう基本的なテクニックですし、ご存じの方も多いでしょう。たとえば次のような使い方です。

Sub Sample1()
    Dim buf As String
    buf = Now & vbCrLf & Date & vbCrLf & Time
    MsgBox buf
End Sub

実行すると次のようになります。

このとき日付はyyyy/mm/dd形式、時刻はH:mm:ss形式のデータが返りますが、この形式は固定されたものではありません。実はWindowsの設定によって、返り値の形式が変わるんです。実際に試してみましょう。

  1. コントロールパネルから「地域と言語のオプション」を実行します。
  2. [地域オプション]タブの[カスタマイズ]ボタンをクリックします。
  3. 最初は時刻の形式を変更します。[時刻]タブの[時刻の形式]リストには一番上の「H:mm:ss」が選択されていると思います。これを「tt hh:mm:ss」に変更します。
  4. 次に日付の形式です。[日付]タブの[短い形式]リストには「yyyy/MM/dd」が設定されていると思いますので、これを「yy/M/d'('ddd')'」に変更します。
  5. [適用]ボタンをクリックして変更を有効にします。

さあ、先ほどと同じコード(Sub Sample1)を実行してみましょう。今度の実行結果は次の通りです。

Date関数、Time関数、Now関数はWindowsの設定によって返り値の形式が変化するんです。これを知らずに、どんなパソコンでも同じ形式が返るって思いこんでいると痛い目にあいます。たとえば、Date関数で取得したデータの左から4文字を抜き出して「現在の年」を調べることがあります。次のようなコードです。

Sub Sample2()
    Dim buf As String
    buf = Date
    MsgBox "今年は、" & Left(buf, 4) & "年です"
End Sub

次のようにマヌケな結果になります。

失笑で済むならけっこうですが、ときには重大なバグを生み出すことにもなりかねません。

VBAには年や月、日あるいは時、分、秒などを調べる専用の関数が用意されています。少しでも安定性を高めたいのでしたら、そうした専用関数の使用をお勧めいたします。

Sub Sample3()
    MsgBox "今年は、" & Year(Date) & "年です"
End Sub

この場合は、日付データを文字列として「左から○文字」のように扱わないで済みますので、上記のようにDate関数の返り値(シリアル値)を直接Year関数に指定した方がいいです。ここで文字列変数を介すると、Windowsの日付設定が和暦になっている場合に誤動作します。掲示板で教えてくださった つるぴん さん、ありがとうございました。