TL;DR —
Nowは日付と時刻を、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 = 正午)。Now、
Date、Time は、その 1 つの数値へ同じ時計を読み込む 3 通りのやり方にすぎません。いったん Double
が見えるようになれば、マクロの中の日付比較のバグはどれも同じ話に行き着きます — 予期しないところに
紛れ込んだ小数、それだけです。
この記事で学べること
- 考え方の軸 — 日付は
Double:整数部 = 日付、小数部 = 時刻 Now、Date、Timeが同じ時計から違う数値を返す理由If stamp = DateがNowの値と無言で一致しない理由 — とその直し方DateとTimeが、システム時計を書き換えるステートメントでもあること- 共有ブックで
Nowが UTC ではなくローカル時刻である理由 - 下にある数値を壊さずに、タイムスタンプを表示用に整える方法
考え方の軸:日付は Double である
すべてが腑に落ちるたった一つの考え方はこれです。VBA の Date 値は数値そのものです。Now を
Double に代入すると、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.0 は False なので、この分岐は
無言で一度も実行されません — エラーもなく、ただ静かに何もしないロジックです。直し方は、判定の前に
時刻を落として同じもの同士を比べることです。
If Int(saved) = Date Then MsgBox "today" ' Int が小数を落とす
If DateValue(saved) = Date Then MsgBox "today" ' DateValue も同じ、こちらは意図が明確
Int(d) は小数を切り捨て、純粋な日付を残します。DateValue も同じことを
しますが、「この値の日付部分」と読めるので、次に読む人にはこちらのほうが明快です。持ち帰るべき
ルールはこれです。Now 由来の値は、両辺を同じ精度にそろえない限り = で比較しない。
「テストでは動いた」系の日付バグは、いつも紛れ込んだ小数が原因です。
Date と Time は、時計を設定するステートメントでもある
一度は誰もが驚く罠がこれです。Date と Time は、時計を読む関数であるだけでなく、時計に
書き込むステートメントでもあります。左辺に代入の形で置くと、コンピューターのシステム時計を
変更します。
x = Date ' 関数 — 今日を x に読み込む
Date = #2030-01-01# ' ステートメント — PC 全体の日付を 2030 に設定
Time = #08:00:00# ' ステートメント — システム時刻を設定
同じ単語なのに正反対の効果で、その分かれ目は = の左に置かれているかどうかだけです。システム時計の
設定はマシン上のすべてのアプリに影響し、管理者権限を要し、そしてスプレッドシートのマクロが
やるべきことではまずありません — うっかりの Date = 何か は、正真正銘に危険なタイプミスです。時計は
読むだけで、決して設定しないこと。Date と Time は代入の右辺に置きましょう。
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 で制御すること。逆方向 — ユーザーが入力したテキストを
日付に変える — には CDate や DateSerial を使います。
率直な結論:数値のどの部分を握っているかを知る
Now、Date、Time は呼ぶのは簡単で、誤用も簡単です。誤用が決してエラーにならず、ただ静かに違う
数値を比べてしまうからです。4 つのルールで全体を覆えます。
Doubleを見る → 整数部は日付、小数部は時刻。Nowは両方、Dateは整数だけ、Timeは 小数だけを持ちます。- 比較の前に正規化する →
stamp = DateではなくInt(stamp) = Date。等値のバグは、いつも 残った小数です。 - 読むだけ、設定しない →
Date/Timeは=の右に置く。左に置くとシステム時計をリセット します。 - 値を保存し、セルを書式化する → 本物の
Nowを保ち、見た目はNumberFormatかFormatで。さもないとSUMと並べ替えが壊れます。
Double の考え方の軸を正しくつかめば、2 つの重い仕事 — 日付の計算と
部品の取り出し — も、もう不思議ではなくなります。
ExcelMaster の活用
本当に時間を奪う日付バグは、静かなものです。一度も発火しない = Date チェック、マクロが
Format(Now, …) をテキストで保存したせいで並べ替えが狂うセル、読む人によって時刻の意味が変わる
共有ログ。どれも、数値のどの部分を握っているかを見失ったところから生まれます。
ExcelMaster は、正しく比較し、正しく
保存するタイムスタンプのロジックを書きます。やりたいことを説明すれば — 「各実行を日付と時刻付きで
記録して」、あるいは「今日より前の日付の行に印を付けて」 — 適切な呼び出し(Now か Date か)を
選び、Int/DateValue で比較を正規化し、保存する値は本物の日付のまま、書式はセル側に置きます。
あなたは捉えたい瞬間を説明するだけ。紛れ込んだ小数の罠なしにそれを捉えるコードを書くのは、それが
やります。
よくある質問
VBA の Now と Date の違いは何ですか?
Now は現在の日付と時刻を、Date は今日の日付を0 時(時刻部なし)で返します。内部では VBA の
日付は Double で、整数部が日付、小数部が時刻です — Now は両方を、Date は整数だけを埋めます。
そのため Now と Date は同じ日でもほとんど等しくならないので、時刻を無視してよい場面ではつねに
Date(または Int(Now))を使いましょう。
VBA で = を使った日付比較がうまくいかないのはなぜですか?
片方が時刻の小数を抱え、もう片方が抱えていないからです。Now から来た値は 46261.6042 のような形で、
Date は 46261.0 なので、Now = Date は False です。比較の前に時刻を落としましょう —
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 はシステムの日付と時刻を変更できますか?
はい、そしてそれが危険な理由です。Date と Time はステートメントでもあります。
Date = #2030-01-01# はコンピューターのシステム日付を、Time = #08:00:00# はその時計を設定し、
すべてのアプリに影響し、たいてい管理者権限を要します。Date と Time は代入の右辺に置き、
時計は読むだけで決して設定しないようにしましょう。
検証環境
検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-26。
関連ガイド: VBA DateAdd・DateDiff — 日付計算 · VBA Weekday・DatePart — 日付の部品を取り出す · VBA Format — 日付・数値の書式設定 · VBA CStr・CDate・Val — 文字列を数値・日付へ変換 · VBA Timer — 経過時間の計測
