Power Automate: getPastTime function

Power Automate: getPastTime function

by: Manuel 12 min read 0 comments

The "getPastTime" function answers a question you ask more often than you'd think. "What was the timestamp a while ago?" You give it a number and a unit, and it hands back a timestamp that far into the past, counted from this exact moment. Everything that looks backward starts here. Items modified in the last 24 hours, tickets older than 30 days, the archive sweep that only touches files nobody has opened since last year.

It's a convenience wrapper. Underneath, it's the "utcNow" function plus a subtraction rolled into one call, which is exactly why people reach for it in Power Automate. Let's look at how it works, where it earns its keep, and the handful of places where it quietly does something you didn't ask for.

Where to find it?

You can use the function anywhere an expression is supported. In practice it turns up inside a "Compose" action, an "Initialize variable" action, a "Condition" action, or in the filter query of an action that fetches records, like the "SharePoint Get Items" action.

Expression picker open on a Compose action, with getPastTime under the Date and time function group

Don't confuse it with "subtractFromTime"

The two functions do the same math, but "getPastTime" always starts from right now, while "subtractFromTime" starts from a timestamp you hand it. If you're counting backward from a created date that came off a list item, "getPastTime" cannot help you. It has no idea that date exists.

Let's look at how to use it.

Usage

The "getPastTime" function takes two required parameters and one optional one:

getPastTime(<interval>, '<timeUnit>', '<format>'?)
Parameter Required Type Description
interval Yes Integer How many time units to subtract from the current moment
timeUnit Yes String The unit to subtract. One of Second, Minute, Hour, Day, Week, Month, or Year
format No String A standard format specifier or a custom format pattern. Defaults to o (ISO 8601), which keeps full precision

The function returns a string, and an invalid format string produces an error rather than a quiet fallback. Notice that the interval is a number and carries no quotes, while the unit is text and does. Mixing those two up is the single most common way to make this function fail.

The simplest possible example asks for the timestamp five days ago:

getPastTime(5, 'Day')

If the current moment is 2026-07-16T09:00:00.0000000Z, this returns 2026-07-11T09:00:00.0000000Z. The time of day comes along for the ride. You asked for five days ago, not for the start of the day five days ago.

Using a custom format

The third parameter shapes the output, and it's the one you want whenever the value is going in front of a person:

getPastTime(5, 'Day', 'D')

That returns Saturday, July 11, 2026. You can also build your own pattern when you need something specific:

getPastTime(1, 'Week', 'dd-MM-yyyy')

That returns 09-07-2026. The formatting rules are the same ones the "formatDateTime" function uses, so anything you already know from there applies here.

Using it in a filter query

This is where the function pays for itself. If you want every item touched in the last 7 days, one line does it, with no variables and no loops:

Modified ge '@{getPastTime(7, 'Day')}'

The "greater than or equals" operator does the comparison and the expression supplies the boundary. Bracket both ends when you want a window rather than an open tail:

Modified ge '@{getPastTime(7, 'Day')}' and Modified le '@{utcNow()}'

That second one uses the "and" operator to join the two halves.

Using a dynamic interval

The interval doesn't have to be hard-coded. If the number of days arrives from a trigger or a variable, feed it through the "int" function so it lands as a number rather than as text:

getPastTime(int(triggerBody()?['DaysBack']), 'Day')

Let's break that down:

  • triggerBody()?['DaysBack'] reads the field from the trigger payload. The "triggerBody" function gets the payload, and the ?['DaysBack'] reaches safely inside it, returning null instead of failing if the field never arrived.
  • int(...) converts that value into a proper integer, which is what the first parameter demands.
  • 'Day' is the unit, quoted because it's text.

Real-world examples

An archive sweep

Joana wants every document nobody has touched in a year moved out of the working library. You never need to compute a date by hand. The filter carries it:

Modified le '@{getPastTime(1, 'Year')}'

Anything older than that boundary comes back, and the boundary slides forward on its own with every run.

A stale ticket escalation

You have a scheduled Flow on a "Recurrence" trigger that chases support tickets left open too long. Manuel's team gives itself 48 hours, so the whole rule is one expression:

Created le '@{getPastTime(48, 'Hour')}' and Status ne 'Closed'

Because "getPastTime" is evaluated fresh on every run, the 48-hour window is always measured from the moment the Flow runs, not from the day you built it.

A "what changed since yesterday" digest

You pull a day's worth of records and mail a summary. Filter at the source rather than fetching everything and thinning the list out afterward:

Modified ge '@{getPastTime(1, 'Day')}'

If the source cannot filter server side, the same boundary works inside a "Filter Array" action, though you pay for it by fetching every row first.

Non-intuitive behaviors

Here are the behaviors that catch people off guard with the "getPastTime" function.

It is always relative to UTC, never to your local time

"Now" means "now in UTC", because that is what the function is built on. This is fine most of the time, and then it isn't.

Say it's 00:30 on a Monday in Lisbon during the summer, which is 23:30 on Sunday in UTC. You call getPastTime(1, 'Day') expecting Sunday, and UTC hands you Saturday, because in UTC it isn't Monday yet. The gap is silent. It never errors, and it only bites at the edges of the day.

This is the most reported problem with the function, and it gets loud at the turn of a month. A getPastTime(1, 'Month') call made just after midnight local on the first of October returns August rather than September, because in UTC the date is still September 30. The fix is always the same. Convert to the local time zone first with the "convertFromUtc" function or the "Convert Time Zone" action, then subtract from the converted value with "subtractFromTime", because "getPastTime" offers no way to move its starting point.

It re-evaluates in every action

The current moment is read when the expression runs, not when the Flow starts. Two actions calling getPastTime(1, 'Day') a few seconds apart produce two different timestamps, and if the Flow is sitting on a "Delay" action or waiting on an approval in between, those few seconds become hours.

Whenever the same past timestamp is needed more than once, calculate it a single time into a variable or a "Compose" action and reference that everywhere else. It costs you one action and buys you a consistent answer.

Months and years clamp to the end of the month

Subtract one month from March 31 and you get February 28, not February 31 and not March 3. The date math refuses to spill over into a day that doesn't exist, so it clamps to the last valid day of the target month instead. The same applies to years, where February 29 minus one year lands on February 28.

This is almost always what you want, but it is not reversible. Subtracting a month and then adding one back does not necessarily return you to where you started, so don't build logic that assumes it does.

A "month" is not a fixed number of days

getPastTime(1, 'Month') is not the same as getPastTime(30, 'Day'). Run both on July 16 and they agree, which is exactly the trap. Run them on May 31 and the first gives you April 30 while the second gives you May 1. One day apart on the calendar, but on opposite sides of a month boundary, which is enough to put them in different reporting periods. If your business rule means 30 days, say 30 days. If it means "the same date last month", say one month.

The output keeps the Z, but only with the default format

The default o format returns something like 2026-07-11T09:00:00.0000000Z, and that trailing Z is what tells every downstream system the value is UTC. The moment you pass a custom format, the Z is gone unless you put it back yourself.

That matters most in filter queries, where a value without a Z is read as the source's local time and quietly shifted. If you're filtering, stay on the default format.

Negative intervals run the clock forwards

Passing a negative number sends you into the future, so getPastTime(-5, 'Day') lands five days from now. It works, but the expression now reads as the opposite of what it does, and the next person to open your Flow will stop and puzzle over it. Use the "getFutureTime" function when you mean the future.

Limitations

It cannot start from any moment other than now

There is no parameter for a starting timestamp, and no way to bolt one on. If the starting point is a created date, a due date, or anything else that isn't the current moment, this is the wrong function. Use "subtractFromTime" when you have a timestamp in hand, or the "addToTime" function with a negative interval if that's already in your expression.

The units are fixed, and quarters are not among them

You get Second, Minute, Hour, Day, Week, Month, and Year. Anything else has to be expressed in terms of those. A quarter is three months and a fortnight is two weeks. A working day is not expressible at all, because the function has no idea that weekends exist.

The result is a string, not a date

The output is text, so you cannot do arithmetic on it directly. If you need to compare or measure, run the value through the "ticks" function to get a number, or use the "dateDifference" function when you want the gap between two timestamps.

Expression size limits

As with every Power Automate expression, you have a ceiling of 8,192 characters. Nesting a few of these inside a larger filter query eats into it faster than you'd think, so break long expressions into "Compose" actions.

Troubleshooting Common Errors

The function expects its first parameter to be an integer

Cause: You quoted the interval. getPastTime('5', 'Day') passes the text 5 where a number is required, and the same thing happens when the value arrives from a variable or a column, since those usually turn up as strings.

Solution: Drop the quotes on a literal, and wrap a dynamic value in the "int" function.

getPastTime(int(triggerBody()?['DaysBack']), 'Day')

The provided time unit is not valid

Cause: The unit isn't one of the seven the function accepts. Days, Mins, and Months are all common attempts, and so is forgetting the quotes entirely. The plurals are the ones that catch people, because they read perfectly well in English and still aren't what the function wants.

Solution: Use one of the seven names exactly as Microsoft documents them, singular and spelled out in full. Second, Minute, Hour, Day, Week, Month, Year. Keep the quotes around the unit, and follow the documented capitalization so the expression matches every example you'll find.

The filter query returns nothing, or returns everything

Cause: The timestamp you generated doesn't match the shape the source expects. A custom format that stripped the Z is the usual culprit, and comparing a date-only value against a column that stores a time is a close second.

Solution: Use the default format inside filter queries so the Z survives, and prefer the "lower than or equals" operator and its siblings over an exact equality check on a date and time column.

Modified le '@{getPastTime(7, 'Day')}'

The date is a day, or a whole month, out from what you expected

Cause: The UTC baseline. Late in the local evening, or early in the local morning, "now" in UTC sits on a different calendar day than the one on your wall, and at the turn of a month that shows up as an entire month gone missing.

Solution: Convert to the local time zone first, then subtract from the converted value with "subtractFromTime". "getPastTime" cannot do this on its own, because it has no starting-point parameter.

subtractFromTime(convertFromUtc(utcNow(), 'GMT Standard Time'), 1, 'Month')

Recommendations

Here are some things to keep in mind when using the "getPastTime" function.

Calculate once, reference everywhere

If the same past timestamp is used in more than one place, work it out a single time into a variable and reuse it. You get one value instead of several slightly different ones, and debugging becomes a matter of reading one action rather than hunting through five. The "variables" function reads it back wherever you need it.

Say what you mean with units

Reach for the unit that matches the business rule rather than the one that's convenient. "Two weeks ago" is getPastTime(2, 'Week'), not getPastTime(14, 'Day'), even though they agree today. When someone later changes the rule to "a month", the intent is already sitting in the expression, waiting to be edited.

Keep the default format for machines

Pass a format string when a person is going to read the value, and leave it alone when a system is. The default carries the Z and the full precision, which is exactly what filter queries, date columns, and comparisons want.

Trim the time when you mean a whole day

"Yesterday" usually means the whole of yesterday, not this time yesterday. If you want the day boundary rather than a rolling 24 hours, wrap the result in the "startOfDay" function.

startOfDay(getPastTime(1, 'Day'))

Always add a comment

Adding a comment will help others understand your expression. Say what the window means in business terms, because "30 days" in the code rarely explains why it's thirty and not sixty.

Final Thoughts

The "getPastTime" function is a small piece of convenience that takes a surprising amount of clutter out of backward-looking logic. One line gives you an archive cut-off, a staleness threshold, or the near end of a filter window, and it stays correct on every run without you touching it. Keep the two rules in mind. It always counts back from now in UTC, and it re-evaluates every single time it runs. Respect those, and it will do exactly what you asked.

Sources

Back to the Power Automate Function Reference

Photo by Markus Winkler on Unsplash

Comments

Spotted a mistake or have a better approach? Let me know. I read and reply to every one.

💬

No comments yet

Be the first to share your thoughts on this article!

Leave a Comment

All comments are reviewed for spam before being displayed 5000 left
Replying to