Dates in formulas

Why does {today} - {trandate} return a decimal instead of a whole number of days?

Updated
saved-searchformuladatestodaytrandatetruncagingsilent-failure

Short answer

Because {today} is a timestamp, not a date. It carries the time of day, so the subtraction leaves a fraction of a day on the end and the result is never a whole number. An equality test against a day count never matches, and a greater-than test moves during the working day. Use TRUNC({today}) - {trandate}, which returns an integer.

Because {today} is a timestamp, not a date. It carries the time of day, so subtracting a stored date from it leaves a fraction of a day on the end, and the answer is never a whole number of days. The fix is one function: TRUNC({today}) - {trandate} returns an integer.

Minimal reproduction

Five formula expressions against the same transaction search, one results column per call. Nothing errors, and every one of them returns a value.

Formula(Text)     TO_CHAR({today},'YYYY-MM-DD HH24:MI:SS')
                  -> 2026-08-22 13:51:01

Formula(Text)     TO_CHAR({trandate},'YYYY-MM-DD HH24:MI:SS')
                  -> 2016-08-29 00:00:00

Formula(Numeric)  {today} - {trandate}
                  -> 3645.57664351851851851851851851851851852

Formula(Numeric)  {today} - TRUNC({today})
                  -> .577326388888888888888888888888888888889

Formula(Numeric)  TRUNC({today}) - {trandate}
                  -> 3645

Read those five together and there is nothing left to argue about. {today} renders with a time on it. {trandate} renders as clean midnight, so the stored date contributes no fraction at all. The isolated fractional part, .5773263888..., is 13:51:01 expressed as a fraction of a day. And the moment {today} is truncated, the same subtraction returns a plain 3645.

The fraction comes entirely from {today}. It is not a rounding artefact and it is not the transaction date.

The three ways this goes wrong, all of them quiet

An equality test never matches. A criteria formula amounting to {today} - {trandate} = 30 returns zero rows, always, because the value is never exactly 30. An empty result set looks like a legitimate answer, and it is the one thing nobody investigates.

A greater-than test drifts. > 30 is off by up to a full day depending on what time of day the search runs, because the fraction being carried is the current clock time.

And the consequence people actually feel: the same saved search returns different aging bucket counts at 9am and at 5pm. Nobody edited it. The boundary moved because the clock moved.

What the run measured is the arithmetic above. The three consequences follow from that arithmetic directly rather than from three separate probes, so treat them as read off the numbers, which is what they are.

The fix

Truncate {today} before you subtract, everywhere, without exception:

TRUNC({today}) - {trandate}

That returned exactly 3645 in the reproduction, an integer, with the same two operands that had produced the long fraction a moment earlier. Once the result is an integer, = 30 becomes a test that can match and a bucket boundary stops moving during the day.

Truncating {trandate} instead does nothing, because {trandate} is already midnight. {trandate} is the only stored date field the run checked, so if you are subtracting some other date field, confirm it carries no time component before assuming the fraction can only have come from {today}.

How to tell if you are affected

Add one Formula(Numeric) column to any transaction search:

{today} - TRUNC({today})

If it returns a non-zero fraction, every day arithmetic formula in that account is carrying it. Then search your saved searches for {today} and check each one for a bare subtraction. An aging report whose numbers you have never quite trusted, or a criteria formula that returns nothing when you are certain rows qualify, are the two symptoms worth going looking for first.

Which clock {today} follows was not established

This run did not determine what time zone or clock {today} tracks. It read 13:51:01 during a run whose browser context was UTC+3, and earlier work on this account family found that SYSDATE is Pacific while CURRENT_DATE follows the session. Deciding which of those {today} matches would need a controlled comparison that was not run, so it is left open here rather than guessed.

That gap does not affect anything above. The fraction exists and TRUNC removes it whatever clock the timestamp came from. It does matter if you are trying to reason about the day boundary itself, for instance whether a search run late in the evening has already rolled over into tomorrow's date. Test that in your own account before you rely on it.

Scope: one sandbox account on NetSuite 2026.1, Administrator role. The searches were built and run ad hoc through the SuiteScript search engine, nlapiCreateSearch and runSearch, without saving anything, on a transaction search.

How this was established

1 probe run against one NetSuite 2026.1 sandbox account on the Administrator role, through the saved search UI and the SuiteScript search engine. Where this page draws a boundary around a finding, that boundary is the edge of what was actually run.

Related

  • How do I group a saved search by month, or format a date, in a formula?

    TO_CHAR({trandate},'YYYY-MM') in a Formula(Text) column gives a sortable month key and honours the format mask exactly. TRUNC({trandate},'MM') in a Formula(Date) column gives the first of the month as a real date, but it renders in the account's date format rather than ISO, so export the text version if anything downstream parses it.

  • Why does my Formula (Numeric) column return 39 decimal places?

    Because Formula (Numeric) does not round at all. It hands back the raw Oracle NUMBER, which is what reaches your CSV export or SuiteScript variable, so 1/3 comes back with 39 decimal places. Formula (Currency) is not the fix: it rounded to 3 dp on some values and 2 on another. Use ROUND(x,2) in the expression.

  • Why does my saved search formula column say "ERROR: Field Not Found" instead of a value?

    Because the search succeeded. A field token in a Results formula did not resolve, and NetSuite writes the literal 22-character string "ERROR: Field Not Found" into the column as its value on every row. It is data, not an exception, it appears in Formula(Numeric) columns, it survives SUM, and NVL does not protect it.

From the blog