Why your Notion days left formula is negative

In the due today article, we used dateBetween() to build Due today, Due tomorrow and Overdue. This article is about the number underneath those labels, and why it sometimes comes back negative. π―
This article is a part of the Fantastic Formulas series. This series features helpful articles about formulas in Notion.
A days-left formula that shows -14 on a renewal that is still two weeks away is not a broken Notion. dateBetween() is a subtraction. First date minus second date. Swap the two dates and every future deadline flips sign. A blank date is the other quiet failure. dateBetween() on an empty cell does not return 0. It returns empty, and an automation that then operates on that date pauses. π
If you want the labels themselves, the due today article already builds them. Today we will only fix the sign, and the blank. Just like in the previous article, I will proceed with a simple database as an example. This time, letβs say we want to track client retainers. π
In this database shown below, you can see 3 properties. First property shows the client name, second one shows the day they signed, and the third property shows the renewal date. β
Example - Simple Retainers database
I am treating 26 Sep 2026 as βtodayβ in the screenshots, so Acme renews in 14 days, Northwind renewed 14 days ago, Harbor renews today, and Studio has no renewal date.
1. dateBetween()
dateBetween() returns the difference between two dates, in a unit you choose. The unit can be "years", "quarters", "months", "weeks", "days", "hours", or "minutes". The syntax is
dateBetween(date1, date2, "days")
dateBetween() function syntax
Read it as date1 minus date2. Notionβs own examples put the later date first when they want a positive number. Counting from an old date up to now is positive. Counting from now up to a future date is also positive. Swap either pair and the sign flips. β
Say we want days left until renewal, and we put now() first because that feels like βstart from todayβ. That is the bug. People usually write it without dateStart(). The sign is already wrong before the clock gets involved. The formula below wraps both sides in dateStart() so we are comparing calendar days, which is the fix from the due today article. It does not fix the order.
dateBetween(dateStart(now()), dateStart(prop("Renewal")), "days")
dateBetween() with the dates backwards
As you can see below, the formula is perfectly working π½
dateBetween() with the dates backwards
- Acme β
-14(the renewal is 14 days away, and the formula says it is 14 days late) - Northwind β
14(the renewal was 14 days ago, and the formula says there are 14 days left) - Harbor β
0(renews today, so the swap does not show) - Studio β empty, because there is no renewal date
Northwind is the row that causes the real damage. A positive number looks healthy. It is not. The deadline has already passed. π
2. Days left, days since
Days left and days since signed are the same function. Only the order changes. Put the deadline first when you want days left. Put today first when you want days since. β
dateBetween(dateStart(prop("Renewal")), dateStart(now()), "days")
Days left, renewal minus today
dateBetween(dateStart(now()), dateStart(prop("Signed")), "days")
Days since signed, today minus the signed date
As you can see below, the formula is perfectly working π½
Same function, two questions
- Acme β
14days left, and730days since they signed on 26 Sep 2024 - Northwind β
-14days left, and365days since they signed on 26 Sep 2025 - Harbor β
0and0, because both dates are today - Studio β empty days left, and
268days since they signed on 1 Jan 2026
A negative days-left number is useful when you asked the right question. It means the renewal is in the past. You want that minus sign on Northwind. You do not want it on Acme. If the number is only off by one in the afternoon, that is the other bug. Go back to the due today article and wrap both sides in dateStart(). β
3. dateEnd()
A date property can be a range, with a start and an end. dateStart() hands back the start. dateEnd() hands back the end. Length of the contract is end minus start. The syntax is
dateBetween(dateEnd(prop("Contract")), dateStart(prop("Contract")), "days")
Contract length, end minus start
Swap those two and Notion does not throw an error. It returns the same number with the sign flipped. Notionβs formula reference uses a one-year range for this exact case: end minus start is 365, start minus end is -365. β
dateBetween(dateStart(prop("Contract")), dateEnd(prop("Contract")), "days")
Same range, dates swapped
As you can see below, the formula is perfectly working π½
dateEnd() minus dateStart()
- Acme, 26 Sep 2025 to 26 Sep 2026 β
365, and-365if you swap - Northwind, 1 Jan 2026 to 1 Jul 2026 β
181, and-181if you swap - Harbor, 26 Sep 2026 to 26 Sep 2027 β
365, and-365if you swap - Studio has no contract range, so both columns stay empty
4. empty()
Studio is the row people forget to test. There is no renewal date. dateBetween() does not turn that into 0. The column stays empty, same as the Reading log row in the due today article. Empty is not false, and it is not zero. empty(0) is true in Notion, which is how you can tell the two apart. π
If this formula sits inside a button or an automation, a blank date is stricter than an empty cell. Notion pauses the automation when the formula operates on an empty date or an empty person. Check the value before you touch it. β
if(
empty(prop("Renewal")),
empty(),
dateBetween(dateStart(prop("Renewal")), dateStart(now()), "days")
)
empty() guard before dateBetween()
empty() on that middle branch is a blank that keeps the result a number. Do not put "" there. A pair of quotes is text, the day count is a number, and the return type becomes unknown. Notionβs own error doc shows the same mistake with a date: if(Date, Date.dateAdd(1, "day"), "") can be a date or text, so an automation will not save. A day count and a pair of quotes fails the same way. π
Say we want the blank row to say something, instead of sitting there looking broken. Both branches have to be text, so wrap the number in format(). β
if(
empty(prop("Renewal")),
"No date",
format(dateBetween(dateStart(prop("Renewal")), dateStart(now()), "days"))
)
Text label when the date is blank
As you can see below, the formula is perfectly working π½
empty() guard, then a text label
Studio says No date. Acme says 14. Northwind says -14. Harbor says 0. Nobody gets a fake zero for a date that was never set.
Conclusion
Now you know why a days-left formula goes negative inside Notion! dateBetween() subtracts the second date from the first. Put the deadline first when you want days left. Put today first when you want days since. On a date range, put dateEnd() first. And if the date might be blank, call empty() before you call dateBetween(). π₯
I hope this article was helpful and easy to understand. At Prototion, we are on mission to make Notion easy for everyone! So we regularly post Helpful articles about Notion like this one. π
Remember to check out the Fantastic Formulas series for more articles about Notion formulas. Doesnβt matter if you are a Notion beginner or a pro, I believe you will find this series helpful. Also, donβt forget to follow us on π¦ Twitter for daily updates, latest Notion template launches and amazing deals & discounts on Premium Notion templates! π
Templates that do this for you
Built by independent makers on Prototion.
Free2024 Couple's Planner
Welcome 2024 with The Couple's Planner, a blend of love & planning. It's a keepsake of your journey together.
FreeDaily Planner
Make yourself feel like playing a game while completing tasks easily with this personalized template.
FreeSimple Task System
@SarthakA free Notion task system with four daily lanes β Top 3, Daily Hustle, Health Weekly and Side Hustle β plus archive, backlog, a linked database and a calendar.