🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Now・Date・Time — 時計を読む、そして Date が「ステートメント」でもある理由

|

Excel VBA の Now・Date・Time — 時計を読む、そして Date が「ステートメント」でもある理由

TL;DRNow は日付時刻を、Date は今日の0 時を、Time時刻だけを返します。 その正体はどれも 1 つの数値です。VBA の日付は Double で、整数部が日付、小数部が時刻です。だから If stamp = Date は、Now から来た値とほとんど一致しません — Now は小数を抱え、Date は 抱えないからです。比較する前に Int(Now)DateValue(Now) で時刻を落としましょう。

Sub ClockDemo()
    Debug.Print Now          ' 2026-08-26 14:30:07  — 日付 + 時刻
    Debug.Print Date         ' 2026-08-26           — 今日の 0 時
    Debug.Print Time         ' 14:30:07             — 時刻だけ
    Debug.Print Int(Now)     ' 2026-08-26           — 時刻を落とした Now = Date
End Sub

VBA の日付は、中身の見えない特別な型ではありません — 仮面をかぶった、ただの Double です。整数部は 1899 年 12 月 30 日からの日数を数え、小数部はその日の時刻を表します(0.5 = 正午)。NowDateTime は、その 1 つの数値へ同じ時計を読み込む 3 通りのやり方にすぎません。いったん Double が見えるようになれば、マクロの中の日付比較のバグはどれも同じ話に行き着きます — 予期しないところに 紛れ込んだ小数、それだけです。

この記事で学べること

  • 考え方の軸 — 日付は Double整数部 = 日付、小数部 = 時刻
  • NowDateTime が同じ時計から違う数値を返す理由
  • If stamp = DateNow の値と無言で一致しない理由 — とその直し方
  • DateTime が、システム時計を書き換えるステートメントでもあること
  • 共有ブックで NowUTC ではなくローカル時刻である理由
  • 下にある数値を壊さずに、タイムスタンプを表示用に整える方法

考え方の軸:日付は Double である

すべてが腑に落ちるたった一つの考え方はこれです。VBA の Date 値は数値そのものです。NowDouble に代入すると、VBA はその仕掛けを見せてくれます。

Dim d As Double
d = Now                       ' 例: 46261.6042
' 46261     -> 1899-12-30 からの日数  -> 日付
' 0.6042    -> 1 日の中の割合         -> 約 14:30 の時刻

整数部はシリアル値の日番号、小数部は 24 時間に対する割合としての時刻です。0.25 は午前 6 時、 0.5 は正午、0.75 は午後 6 時。あとはすべてここから導けます。1 を足せば 1 日進み、1/24 を足せば 1 時間進みます。3 つの時計関数の違いは、数値のどの部分を埋めるかだけです。

  • Now両方を埋めます — 整数の日付小数の時刻。
  • Date整数だけを埋めます — 今日、小数は 0(0 時)に固定。
  • Time小数だけを埋めます — その日の時刻、整数部は 0

これがモデルのすべてです。この記事の残りは、どの部分が埋まっているかを忘れたときに起きることの話です。

Now・Date・Time:一つの時計を 3 通りに読む

いま本当に訊きたい問いに合うものを選びましょう。

  • Now — 日付と時刻がそろったタイムスタンプ。何かがいつ起きたかを記録するのに使います (ws.Range("A1") = Now)。
  • Date — 今日のカレンダー日付、0 時ちょうど。この請求は期限切れか、今日は週末か、といった どの日かのロジックに使います。時刻はノイズです。
  • Time — 日付なしの時刻。時刻を刻む、あるいは 1 日の中の実時刻を測るのに使います。
Range("A1") = Now      ' 2026-08-26 14:30:07  — イベントを記録
Range("A2") = Date     ' 2026-08-26           — 期限日の列
Range("A3") = Time     ' 14:30:07             — シフト開始時刻

Now = Date + Time は秒単位まで成り立ちます。数値がまさにそのように組み立てられているからです — Date が整数を、Time が小数を供給します。

If stamp = Date が Now の値と一致しない理由

これが目玉のバグで、Double から直接導かれます。Now でタイムスタンプを保存し、あとでそれが 今日起きたかを判定します。

saved = Now                       ' 46261.6042  (時刻の小数を持つ)
' ...後で...
If saved = Date Then MsgBox "today"   ' Date は 46261.0000 — 決して等しくない

Date は整数、saved は小数を抱えています。46261.6042 = 46261.0False なので、この分岐は 無言で一度も実行されません — エラーもなく、ただ静かに何もしないロジックです。直し方は、判定の前に 時刻を落として同じもの同士を比べることです。

If Int(saved) = Date Then MsgBox "today"        ' Int が小数を落とす
If DateValue(saved) = Date Then MsgBox "today"  ' DateValue も同じ、こちらは意図が明確

Int(d) は小数を切り捨て、純粋な日付を残します。DateValue も同じことを しますが、「この値の日付部分」と読めるので、次に読む人にはこちらのほうが明快です。持ち帰るべき ルールはこれです。Now 由来の値は、両辺を同じ精度にそろえない限り = で比較しない。 「テストでは動いた」系の日付バグは、いつも紛れ込んだ小数が原因です。

Date と Time は、時計を設定するステートメントでもある

一度は誰もが驚く罠がこれです。DateTime は、時計を読む関数であるだけでなく、時計に 書き込むステートメントでもあります。左辺に代入の形で置くと、コンピューターのシステム時計を 変更します。

x = Date              ' 関数 — 今日を x に読み込む
Date = #2030-01-01#   ' ステートメント — PC 全体の日付を 2030 に設定
Time = #08:00:00#     ' ステートメント — システム時刻を設定

同じ単語なのに正反対の効果で、その分かれ目は = の左に置かれているかどうかだけです。システム時計の 設定はマシン上のすべてのアプリに影響し、管理者権限を要し、そしてスプレッドシートのマクロが やるべきことではまずありません — うっかりの Date = 何か は、正真正銘に危険なタイプミスです。時計は 読むだけで、決して設定しないこと。DateTime は代入の右辺に置きましょう。

Now は UTC ではなくローカル時刻

Now はマシンのローカル時計を読みます — その値はユーザーのタイムゾーンとサマータイム設定に 左右されます。地域をまたいで共有されるブックでは、2 人が同じボタンを押しても異なる時刻が刻まれ、 しかもどちらも UTC ではありません。VBA には UTC を返す組み込み関数がありません。協定世界時を 得るには Windows API 呼び出し(GetSystemTime)かヘルパーが必要です。

' Now = ローカルの壁時計の時刻 — 1 台のマシンなら問題ないが、
' ファイルがタイムゾーンをまたいだ瞬間にあいまいになる。
Range("Log") = Now

1 人のユーザーのブックなら、これはまさに正しく、シンプルです。複数の地域が読むログなら、(API 経由で) UTC を保存するか、タイムスタンプの隣にタイムゾーンを記録しましょう — さもないと「10:00」という記録は、 それが誰の 10:00 かを知らなければ何の意味も持ちません。

下にある数値を壊さずにタイムスタンプを表示する

日付を思いどおりに見せるには Format を使います — ただし返るのはテキスト であって日付ではないことを忘れないでください。だから表示専用です。

MsgBox Format(Now, "yyyy-mm-dd hh:nn:ss")   ' メッセージ用の String
cell.Value = Now                            ' 本物の Double を保存し...
cell.NumberFormat = "yyyy-mm-dd"            ' ...値ではなくセルを書式化する

cell.Value = Format(Now, ...) と書くと、セルには日付に見える文字列が入り、その結果 SUM、 並べ替え、日付フィルターがすべて壊れます。セルがテキストになるからです。正しい習慣は、本物の Now 値を保存し、その見た目を NumberFormat で制御すること。逆方向 — ユーザーが入力したテキストを 日付変える — には CDateDateSerial を使います。

率直な結論:数値のどの部分を握っているかを知る

NowDateTime は呼ぶのは簡単で、誤用も簡単です。誤用が決してエラーにならず、ただ静かに違う 数値を比べてしまうからです。4 つのルールで全体を覆えます。

  • Double を見る → 整数部は日付、小数部は時刻。Now は両方、Date は整数だけ、Time は 小数だけを持ちます。
  • 比較の前に正規化するstamp = Date ではなく Int(stamp) = Date。等値のバグは、いつも 残った小数です。
  • 読むだけ、設定しないDate/Time= の右に置く。左に置くとシステム時計をリセット します。
  • 値を保存し、セルを書式化する → 本物の Now を保ち、見た目は NumberFormatFormat で。さもないと SUM と並べ替えが壊れます。

Double の考え方の軸を正しくつかめば、2 つの重い仕事 — 日付の計算部品の取り出し — も、もう不思議ではなくなります。

ExcelMaster の活用

本当に時間を奪う日付バグは、静かなものです。一度も発火しない = Date チェック、マクロが Format(Now, …) をテキストで保存したせいで並べ替えが狂うセル、読む人によって時刻の意味が変わる 共有ログ。どれも、数値のどの部分を握っているかを見失ったところから生まれます。

ExcelMaster は、正しく比較し、正しく 保存するタイムスタンプのロジックを書きます。やりたいことを説明すれば — 「各実行を日付と時刻付きで 記録して」、あるいは「今日より前の日付の行に印を付けて」 — 適切な呼び出し(NowDate か)を 選び、Int/DateValue で比較を正規化し、保存する値は本物の日付のまま、書式はセル側に置きます。 あなたは捉えたい瞬間を説明するだけ。紛れ込んだ小数の罠なしにそれを捉えるコードを書くのは、それが やります。

よくある質問

VBA の Now と Date の違いは何ですか?

Now は現在の日付時刻を、Date は今日の日付を0 時(時刻部なし)で返します。内部では VBA の 日付は Double で、整数部が日付、小数部が時刻です — Now は両方を、Date は整数だけを埋めます。 そのため NowDate は同じ日でもほとんど等しくならないので、時刻を無視してよい場面ではつねに Date(または Int(Now))を使いましょう。

VBA で = を使った日付比較がうまくいかないのはなぜですか?

片方が時刻の小数を抱え、もう片方が抱えていないからです。Now から来た値は 46261.6042 のような形で、 Date46261.0 なので、Now = DateFalse です。比較の前に時刻を落としましょう — If Int(stamp) = Date Then …If DateValue(stamp) = Date Then …。2 つの日付を = で比べるのは、 両方を同じ精度に正規化したときだけにします。

VBA で現在の時刻だけを取得するには?

Time 関数を使います。t = Time は日付なしの時刻を返します(数値の整数部は 0)。Now から得た タイムスタンプがあって時刻部分だけがほしいなら、日付部を引きます — t = Now - Int(Now) で小数が 残ります。テキストとして表示するには Format(Time, "hh:nn:ss") を使います。

VBA の Now は UTC 時刻を返しますか?

いいえ。Now はマシンのローカルの壁時計の時刻を、タイムゾーンとサマータイムのオフセット込みで 返します。VBA には UTC の組み込み関数がありません。協定世界時には GetSystemTime のような Windows API 呼び出しが必要です。地域をまたいで共有するブックでは、UTC を保存するか、タイムスタンプの隣に タイムゾーンを記録しましょう。さもないと記録された時刻はあいまいになります。

VBA はシステムの日付と時刻を変更できますか?

はい、そしてそれが危険な理由です。DateTimeステートメントでもあります。 Date = #2030-01-01# はコンピューターのシステム日付を、Time = #08:00:00# はその時計を設定し、 すべてのアプリに影響し、たいてい管理者権限を要します。DateTime は代入の右辺に置き、 時計は読むだけで決して設定しないようにしましょう。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-26。

関連ガイド: VBA DateAdd・DateDiff — 日付計算 · VBA Weekday・DatePart — 日付の部品を取り出す · VBA Format — 日付・数値の書式設定 · VBA CStr・CDate・Val — 文字列を数値・日付へ変換 · VBA Timer — 経過時間の計測