TL;DR —
Nowreturns the date and time,Datereturns today at midnight, andTimereturns the time-of-day only. Underneath they are all one number: a VBA date is aDoublewhere the integer part is the day and the fraction is the time. That is whyIf stamp = Datealmost never matches a value that came fromNow—Nowcarries a fraction,Datedoes not. Drop the time withInt(Now)orDateValue(Now)before you compare.
Sub ClockDemo()
Debug.Print Now ' 2026-08-26 14:30:07 — date + time
Debug.Print Date ' 2026-08-26 — today at midnight
Debug.Print Time ' 14:30:07 — time only
Debug.Print Int(Now) ' 2026-08-26 — Now with the time dropped = Date
End Sub
A VBA date is not a special type you cannot see into — it is a plain Double wearing a mask. The whole
part counts days since 30 December 1899; the fractional part is the time of day (0.5 = noon).
Now, Date, and Time are just three ways of reading the same clock into that number. Once you can
see the Double, every date-comparison bug in your macros turns out to be the same story: a stray
fraction where you did not expect one.
What you'll learn
- The mental model — a date is a
Double: integer = day, fraction = time - Why
Now,Date, andTimereturn different numbers from the same clock - Why
If stamp = Datesilently never matches aNowvalue — and how to fix it - That
DateandTimeare also statements that reset the system clock - Why
Nowis local time, not UTC, in a shared workbook - How to format a stamp for display without breaking the number underneath
The mental model: a date is a Double
The single idea that makes all of this click: a VBA Date value is a number. Assign Now to a
Double and VBA shows you the machinery:
Dim d As Double
d = Now ' e.g. 46261.6042
' 46261 -> days since 1899-12-30 -> the date
' 0.6042 -> fraction of a day -> ~14:30 the time
The integer part is the serial day number; the fractional part is the time as a fraction of 24
hours. 0.25 is 6 a.m., 0.5 is noon, 0.75 is 6 p.m. Everything else follows from this. Adding 1
moves you one day; adding 1/24 moves you one hour. The three clock functions differ only in which
part of the number they fill in:
Nowfills in both parts — integer day and fractional time.Datefills in only the integer — today, with the fraction forced to0(midnight).Timefills in only the fraction — the time of day, with the integer part0.
That is the whole model. The rest of this guide is what happens when you forget which part is filled in.
Now vs Date vs Time: three reads of one clock
Reach for the one that matches the question you are actually asking:
Now— a full timestamp, date and time. Use it to record when something happened (ws.Range("A1") = Now).Date— today's calendar date at midnight. Use it for which day logic — is this invoice overdue, is today a weekend — where the time of day is noise.Time— the time of day with no date. Use it to stamp a time or measure a wall-clock moment within a day.
Range("A1") = Now ' 2026-08-26 14:30:07 — logged an event
Range("A2") = Date ' 2026-08-26 — a due-date column
Range("A3") = Time ' 14:30:07 — a shift start time
Now = Date + Time is true to the second, because that is literally how the number is built: Date
supplies the integer, Time supplies the fraction.
Why If stamp = Date never matches a Now value
This is the headline bug, and it follows directly from the Double. You store a timestamp with Now,
then later test whether it happened today:
saved = Now ' 46261.6042 (has a time fraction)
' ...later...
If saved = Date Then MsgBox "today" ' Date is 46261.0000 — NEVER equal
Date is a whole number; saved carries a fraction. 46261.6042 = 46261.0 is False, so the branch
silently never fires — no error, just logic that quietly does nothing. The fix is to compare like with
like by dropping the time before the test:
If Int(saved) = Date Then MsgBox "today" ' Int drops the fraction
If DateValue(saved) = Date Then MsgBox "today" ' DateValue does the same, by intent
Int(d) truncates the fraction, leaving the pure date. DateValue does the same but
reads as "the date part of this value," which is clearer to the next person. The rule to carry away:
never compare a Now-derived value with = unless both sides are normalized to the same precision.
The "it worked in testing" date bug is always a stray fraction.
Date and Time are also statements that set the clock
Here is the trap that surprises everyone once: Date and Time are not only functions that read the
clock — they are also statements that write it. With an assignment on the left, they change the
computer's system clock:
x = Date ' FUNCTION — reads today into x
Date = #2030-01-01# ' STATEMENT — sets the WHOLE COMPUTER's date to 2030
Time = #08:00:00# ' STATEMENT — sets the system time
Same word, opposite effect, decided entirely by whether it sits on the left of an =. Setting the
system clock affects every application on the machine, needs administrator rights, and is almost
never what a spreadsheet macro should do — a stray Date = something is a genuinely dangerous typo.
Read the clock, never set it: keep Date and Time on the right-hand side of your assignments.
Now is local time, not UTC
Now reads the machine's local clock — its value depends on the user's time zone and daylight-saving
setting. In a workbook shared across regions, two people clicking the same button stamp two different
times, and neither is UTC. VBA has no built-in UTC function; getting universal time needs a Windows
API call (GetSystemTime) or a helper:
' Now = local wall-clock time — fine for one machine,
' ambiguous the moment the file crosses a time zone.
Range("Log") = Now
For a single user's workbook this is exactly right and simple. For a log that several regions will read, either store UTC (via the API) or record the time zone alongside the stamp — otherwise a "10:00" entry means nothing without knowing whose 10:00 it was.
Displaying a stamp without breaking the number
To show a date the way you want, use Format — but remember it returns text,
not a date, so it is for display only:
MsgBox Format(Now, "yyyy-mm-dd hh:nn:ss") ' a String for a message
cell.Value = Now ' store the real Double...
cell.NumberFormat = "yyyy-mm-dd" ' ...and format the CELL, not the value
Writing cell.Value = Format(Now, ...) puts a string that looks like a date into the cell, and then
SUM, sorting, and date filters all break because the cell is text. The correct habit: store the real
Now value and control its appearance with NumberFormat. To go the other way — turn user-typed text
into a date — use CDate or DateSerial.
The honest verdict: know which part of the number you hold
Now, Date, and Time are trivial to call and easy to misuse, because the misuse never raises an
error — it just quietly compares the wrong numbers. Four rules cover the whole surface:
- See the
Double→ integer is the day, fraction is the time.Nowhas both;Datehas only the integer;Timehas only the fraction. - Normalize before you compare →
Int(stamp) = Date, neverstamp = Date. The equality bug is always a leftover fraction. - Read, never set → keep
Date/Timeon the right of=. On the left they reset the system clock. - Store the value, format the cell → keep the real
Now; useNumberFormatorFormatfor how it looks, orSUMand sorting break.
Get the Double mental model right and the two heavy lifts — doing math on dates
and pulling parts back out — stop being mysterious too.
How ExcelMaster helps
The date bugs that cost real time are the silent ones: a = Date check that never fires, a cell that
sorts wrong because a macro stored Format(Now, …) as text, a shared log whose times mean different
things to different readers. Each one comes from losing track of which part of the number you are holding.
ExcelMaster writes the timestamp logic that
compares correctly and stores correctly. Describe the job — "log each run with a date and time," or "flag
rows dated before today" — and it produces the right call (Now vs Date), normalizes the comparison
with Int/DateValue, and keeps the stored value a real date with the formatting on the cell. You
describe the moment you want to capture; it writes the code that captures it without the stray-fraction
trap.
Frequently asked questions
What is the difference between Now and Date in VBA?
Now returns the current date and time; Date returns today's date at midnight (no time part).
Under the hood a VBA date is a Double where the integer is the day and the fraction is the time — Now
fills in both, Date fills in only the integer. Because of that, Now and Date are almost never equal
even on the same day, so use Date (or Int(Now)) whenever the time of day should not matter.
Why does my date comparison with = never work in VBA?
Because one side carries a time fraction and the other does not. A value from Now looks like
46261.6042, while Date is 46261.0, so Now = Date is False. Drop the time before comparing:
If Int(stamp) = Date Then … or If DateValue(stamp) = Date Then …. Only compare two dates with =
when both have been normalized to the same precision.
How do I get just the current time in VBA?
Use the Time function: t = Time returns the time of day with no date (the integer part of the number
is zero). If you have a full timestamp from Now and want only its time portion, subtract the date part:
t = Now - Int(Now), which leaves the fraction. To display it as text use Format(Time, "hh:nn:ss").
Does Now return UTC time in VBA?
No. Now returns the machine's local wall-clock time, including its time-zone and daylight-saving
offset. VBA has no built-in UTC function; for universal time you need a Windows API call such as
GetSystemTime. In a workbook shared across regions, store UTC or record the time zone next to the stamp,
or a logged time is ambiguous.
Can VBA change the system date and time?
Yes, and that is why it is dangerous. Date and Time are also statements: Date = #2030-01-01#
sets the computer's system date and Time = #08:00:00# sets its clock, affecting every application and
usually requiring administrator rights. Keep Date and Time on the right-hand side of an
assignment so you only ever read the clock, never set it.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-08-26.
Related guides: VBA DateAdd & DateDiff · VBA Weekday & DatePart · VBA Format · VBA CStr, CDate & Val · VBA Timer
