How to show Due today, Due tomorrow and Overdue in Notion formulas

In the previous article, we learned about logic functions that are used in formulas inside Notion! This article puts those functions to work on dates. Similar to the previous article, I will explain every step along with an example for each step. 💯
This article is a part of the Fantastic Formulas series. This series features helpful articles about formulas in Notion.
If you have ever built a task database in Notion, you already know the pain. A due date sitting in a column does not tell you much on its own. You still have to squint at the calendar and work out whether that row is late, due today, or still a few days away. 👀
The labels people look for the most are these four:
- Overdue
- Due today
- Due tomorrow
- X days left
Today we will build all four with formulas, using the same if() style from the last article, then a cleaner ifs() version. Along the way we will fix the off-by-one day that makes a task say “Due tomorrow” on the morning it is actually due, which is easily the most common complaint I see about date formulas. ✅
Just like in the previous article, I will proceed with a simple database as an example to make it easily understandable. This time, let’s say we want to track assignments. 👀
In this database shown below, you can see 3 properties. First property shows the name of the assignment, second one shows the due date and the third property shows the status. ✅
Example - Simple Assignments database
I am treating 8 Sep 2026 as “today” in the screenshots, so Anatomy quiz is due today, Care plan is due tomorrow, Lab report is already late, Midterm notes is 12 days out, and Reading log has no due date.
1. dateBetween()
Before we write any labels, we need a number. How many days are there between today and the due date? dateBetween() gives us that. The syntax is
dateBetween(prop("Due date"), now(), "days")
dateBetween() function syntax
Let’s add a formula property called Days left and paste that in. Then look closely at the Care plan row, because this is where most people’s formula quietly goes wrong.
now() is not midnight. It is the current moment, right down to the second. A due date in Notion, on the other hand, is stored at midnight when you have not switched the time on. So if you write the formula the obvious way and check it at 3 in the afternoon, Notion is measuring from 3pm today to midnight tomorrow. That gap is 9 hours, not 24.
And dateBetween() with "days" counts whole days only. Anything under 24 hours is not a full day yet, so it comes back as 0. Tomorrow reads as zero days away, your “Due tomorrow” branch never fires, and the row wears the wrong label for the whole afternoon. ✅
2. dateStart()
The fix is dateStart(). It takes a date and hands back the start of it — midnight — which is exactly what we want on both sides of the comparison.
dateBetween(dateStart(prop("Due date")), dateStart(now()), "days")
dateBetween() with dateStart() on both sides
Wrapping only one side does not help, and I have watched people lose an hour to that. dateStart(now()) is the half that matters most, since now() is the one carrying a time. Wrap both and you are comparing calendar days to calendar days, which is how a human reads a due date anyway.
The same rule applies when you compare two dates directly instead of counting days between them. This is the comparison people reach for first:
now() < dateStart(prop("Due date"))
Comparing now() against a due date
It works, but it is answering a slightly different question than you think. It is true until midnight of the due date, so on the due day itself it flips to false at 00:00 and the row reads as past. If you want “is this row still in the future in calendar terms”, compare like for like:
dateStart(now()) < dateStart(prop("Due date"))
Comparing calendar day to calendar day
As you can see below, the formula is perfectly working 🔽
dateBetween() with dateStart() results
- Anatomy quiz →
0(due today) - Care plan →
1(due tomorrow) - Lab report →
-3(already late) - Midterm notes →
12 - Reading log → empty, because there is no due date
Keep this property if you like seeing the raw number. For the rest of the article we will put dateBetween() inside the label formula, so you do not need two columns. If you want a fuller tour of the date functions themselves, the date and time functions article covers dateAdd(), formatDate() and the rest.
3. if()
The IF function is used to test a condition and return one value if the condition is true and another value if the condition is false. We used it in the last article for inventory stock. Same idea, different question: is this row overdue? The syntax of the IF function is
if(condition, "value_if_true", "value_if_false")
if() function syntax
A row should only say Overdue when three things are true at once. There is a due date. That date is before today. The status is not Done. ✅
if(empty(prop("Due date")), "",
if(prop("Status") == "Done", "",
if(dateStart(prop("Due date")) < dateStart(now()), "Overdue", "")))
Nested if() statement for Overdue
This is the same nested if() pattern from the logic article, and if nesting is still new to you, this walkthrough of if formulas goes slower. Empty date? Show nothing. Already done? Show nothing. Date in the past? Show Overdue.
As you can see below, the formula is perfectly working 🔽
Single nested if() for Overdue
Only Lab report is tagged Overdue. Anatomy quiz is due today, so it stays blank. Reading log is Done, so it stays blank even if you later add an old date to it.
That is useful, but it only answers the one question. Let’s get the other three labels in there too.
4. ifs()
Nested if() gets messy the moment you want four labels instead of one. ifs() is the same idea, just written as a list of conditions. The first true condition wins. The syntax is
ifs(condition1, "value1", condition2, "value2", "fallback")
ifs() function syntax
Say we want Due today, Due tomorrow, Overdue, and a leftover “X days left” label. We can also wrap the whole thing in lets() so we only calculate the day count once. ✅
lets(
due, prop("Due date"),
days, dateBetween(dateStart(due), dateStart(now()), "days"),
ifs(
empty(due), "",
prop("Status") == "Done", "",
days < 0, "Overdue",
days == 0, "Due today",
days == 1, "Due tomorrow",
format(days) + " days left"
)
)
ifs() statement for due labels
Read it top to bottom.
- No due date → blank
- Status is Done → blank
- Negative days → Overdue
- Zero days → Due today
- One day → Due tomorrow
- Anything else →
12 days left
The order matters here. If you put days == 0 before the Done check, a finished assignment due today would still say Due today. Put the skip conditions first. ✅
As you can see below, the formula is perfectly working 🔽
ifs() statement results
Anatomy quiz is Due today, Care plan is Due tomorrow, Lab report is Overdue, Midterm notes is 12 days left, and Reading log stays empty.
If your labels are still one day out, go back to step 2. Nine times out of ten there is a now() sitting there without dateStart() around it.
5. style()
The labels work, but Overdue in plain text is easy to miss in a long table. style() paints the text. Valid styles are "b", "i", "u", "s" and "c". Valid colors are "red", "orange", "yellow", "green", "blue", "purple", "pink", "gray" and "brown". Add "_background" if you want a pill. ✅
The syntax looks like this
style("Overdue", "red", "b")
style() function syntax
Swap the plain strings from the last formula with styled ones:
lets(
due, prop("Due date"),
days, dateBetween(dateStart(due), dateStart(now()), "days"),
ifs(
empty(due), "",
prop("Status") == "Done", "",
days < 0, style("Overdue", "red", "b"),
days == 0, style("Due today", "orange", "b"),
days == 1, style("Due tomorrow", "yellow", "b"),
format(days) + " days left"
)
)
ifs() + style() example
As you can see below, the styling comes through 🔽
style() on due labels
Overdue jumps out in red, Due today sits in orange and Due tomorrow is yellow. I have deliberately left the later rows unstyled so that a long table still has somewhere quiet to rest.
You can sort or filter the database by this formula property once it is in. Grouping by the Due label puts the Overdue pile on top of the list without any extra rollup, and if you would rather drive a Select property from the same logic, we covered changing a tag automatically from another property separately.
Conclusion
Now you know how to turn a due date into Due today, Due tomorrow and Overdue inside Notion! The pieces are the same logic functions from the last article, plus dateBetween(), dateStart(), lets(), ifs() and style().
The one to remember is dateStart(). dateBetween() counts whole days and now() carries a time, so without it your formula measures a nine hour gap and calls it zero days. Wrap both sides, and the labels agree with the calendar on the wall. 🔥
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.
FreeList of languages
@LumibernThis is a simple list of 184 languages with the corresponding language codes according to ISO 639-1.