Category: Power Platform
-

Get the difference between two dates (Updated 2025)
Many Power Automate users encounter issues with the
dateDifference()function when calculating the difference between two dates. The problem arises when the output format varies depending on the duration, causing errors in extracting Days, Hours, Minutes, and Seconds.This blog provides a robust and easy-to-implement solution that works seamlessly in all scenarios, including durations less than a day. Learn how to use a single expression with conditional logic to avoid these common pitfalls and ensure your date calculations are accurate every time. This is your ultimate fix for handling
dateDifference()errors!
The Flow
- Compose action: named StartDate =
2024-12-10T15:58:28 - Compose action: named EndDate =
2024-12-10T19:22:20 - Compose action: uses dateDifference() expression. see below
Below is the expression used in the ‘Date Difference’ compose action. It dynamically handles all scenarios—when days are included and when they are not (same with hours and minutes).
dateDifference expression
Create a compose action for StartDate and EndDate
if( contains( dateDifference(outputs('StartDate'), outputs('EndDate')), '.' ), json( concat( '{"Days":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[0])), ',"Hours":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[0])), ',"Minutes":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[1])), ',"Seconds":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[2])), '}' ) ), json( concat( '{"Days":0', ',"Hours":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[0])), ',"Minutes":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[1])), ',"Seconds":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[2])), '}' ) ) )How it works
- The
if()function checks if thedateDifference()result contains a.(dot). - If it does, it means the result has a days component (e.g.,
1268.04:15:30), so we parse out Days, Hours, Minutes, and Seconds accordingly. - If it does not, it means the result is less than a day (e.g.,
12:57:47.2544602), so we treat Days as 0 and parse Hours, Minutes, and Seconds directly from the string.
Result:
This will produce a JSON object like:
{
"Days": 1268,
"Hours": 4,
"Minutes": 15,
"Seconds": 30
}
Or{
"Days": 0,
"Hours": 12,
"Minutes": 57,
"Seconds": 47
}Steps to Access Each Value
If you use the fixed expression directly in a Compose action (e.g., named
Date_Difference), you can reference the fields like this:- Days:
outputs('Date_Difference')?['Days'] - Hours:
outputs('Date_Difference')?['Hours'] - Minutes:
outputs('Date_Difference')?['Minutes'] - Seconds:
outputs('Date_Difference')?['Seconds']
Use these expressions in subsequent actions (like another Compose, a Condition, or Apply to Each) to reference the specific values.

Download my Flow
You can easily copy and paste actions in Power Automate. Allowing you to copy and paste my example.
Classic designer
Step 1: Copy the code snippet
{"id":"b6b531e2-b7b5-4a9e-86bd-7e2a069529a0","brandColor":"#8C3900","connectionReferences":{},"connectorDisplayName":"Control","icon":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KIDxwYXRoIGQ9Im0wIDBoMzJ2MzJoLTMyeiIgZmlsbD0iIzhDMzkwMCIvPg0KIDxwYXRoIGQ9Im04IDEwaDE2djEyaC0xNnptMTUgMTF2LTEwaC0xNHYxMHptLTItOHY2aC0xMHYtNnptLTEgNXYtNGgtOHY0eiIgZmlsbD0iI2ZmZiIvPg0KPC9zdmc+DQo=","isTrigger":false,"operationName":"Get_date_difference_object","operationDefinition":{"type":"Scope","actions":{"StartDate":{"type":"Compose","inputs":"2024-12-10T15:58:28","runAfter":{}},"EndDate":{"type":"Compose","inputs":"2024-12-10T19:22:20","runAfter":{"StartDate":["Succeeded"]}},"Date_Difference":{"type":"Compose","inputs":"@if(\r\n contains(\r\n dateDifference(outputs('StartDate'), outputs('EndDate')), \r\n '.'\r\n ),\r\n json(\r\n concat(\r\n '{\"Days\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[0])),\r\n ',\"Hours\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[0])),\r\n ',\"Minutes\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[1])),\r\n ',\"Seconds\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[2])),\r\n '}'\r\n )\r\n ),\r\n json(\r\n concat(\r\n '{\"Days\":0',\r\n ',\"Hours\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[0])),\r\n ',\"Minutes\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[1])),\r\n ',\"Seconds\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[2])),\r\n '}'\r\n )\r\n )\r\n)","runAfter":{"EndDate":["Succeeded"]},"metadata":{"operationMetadataId":"03c8d578-576a-41a3-8d63-609a15ce594b"}}},"runAfter":{"Add_to_time":["Succeeded"]}}}Step 2: In Power Automate when adding a new action click
My clipboard.
Step 3: Ctrl + V

New designer
Step 1: Copy the code snippet
{"nodeId":"Get_date_difference_object-copy","serializedOperation":{"type":"Scope","actions":{"StartDate":{"type":"Compose","inputs":"2024-12-10T15:58:28"},"EndDate":{"type":"Compose","inputs":"2024-12-10T19:22:20","runAfter":{"StartDate":["Succeeded"]}},"Date_Difference":{"type":"Compose","inputs":"@if(\r\n contains(\r\n dateDifference(outputs('StartDate'), outputs('EndDate')), \r\n '.'\r\n ),\r\n json(\r\n concat(\r\n '{\"Days\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[0])),\r\n ',\"Hours\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[0])),\r\n ',\"Minutes\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[1])),\r\n ',\"Seconds\":', string(int(split(split(dateDifference(outputs('StartDate'), outputs('EndDate')), '.')[1], ':')[2])),\r\n '}'\r\n )\r\n ),\r\n json(\r\n concat(\r\n '{\"Days\":0',\r\n ',\"Hours\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[0])),\r\n ',\"Minutes\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[1])),\r\n ',\"Seconds\":', string(int(split(dateDifference(outputs('StartDate'), outputs('EndDate')), ':')[2])),\r\n '}'\r\n )\r\n )\r\n)","runAfter":{"EndDate":["Succeeded"]},"metadata":{"operationMetadataId":"03c8d578-576a-41a3-8d63-609a15ce594b"}}},"runAfter":{"Add_to_time":["Succeeded"]}},"allConnectionData":{},"staticResults":{},"isScopeNode":true,"mslaNode":true}Step 2: In Power Automate click the + to add an action. Click
Paste an action
Conclusion
That’s it! pretty easy right? if you encounter any issues, comment below!
- Compose action: named StartDate =
-

Creating Navigation Buttons for Different Views in Model-Driven Apps
When building model-driven apps, one common frustration is the limitation of adding a single table with only a default view. For example, if you have a Contacts table with a Choice field, and you’ve created a view for each choice, users have to select Contacts first, then navigate to the desired view manually.
But what if you could streamline this process by adding separate navigation buttons for each view directly in the app’s left-hand navigation bar? This blog post will walk you through how to achieve that using URL-based navigation—no extra coding required.
The Scenario
This is a small example, but the functionality I am about to show you is very powerful, and can help streamline UX.
Imagine you have:
- A Contacts table in Dataverse.
- A Choice field in the Contacts table called
Contact Typewith options like Client, Vendor, and Partner. - Custom views for each Contact Type, such as Client Contacts, Vendor Contacts, and Partner Contacts.
By default, when adding the Contacts table to your app, only one button appears on the navigation bar, leading to the default view. Users must manually switch to the other views. This approach isn’t user-friendly for frequent switching between views. Especially when some users only care about certain contact types.
Setup
Step 1: Create views
First you will want to create a view for each button on the navigation. In my case I created a view for Vendor Contacts, and Client Contacts. Each view I added a simple filter to show only that
Contact TypeExample:

Step 2: Get the entitylist ID and view ID
Play your model driven app, select the Table and choose the view.
Now look at the URL, and copy everything afterentitylist&etn=
So in my example the Vendor Contacts view URL is:
contact&viewid=ee7b9134-7cb2-ef11-a72f-000d3af40ac9&viewType=1039Next add this to the beginning of the URL you just copied:
/main.aspx?pagetype=entitylist&etn=So my final URL will be:
/main.aspx?pagetype=entitylist&etn=contact&viewid=ee7b9134-7cb2-ef11-a72f-000d3af40ac9&viewType=1039This will be the URL we use as our navigation link.
Step 3: Edit model-driven app to add URL
Edit your model driven app, click +New, and select Navigation link

Add the URL we built in Step 2, and give it a name, click Add

NOTE: If you get an error, it means your URL is wrong. Follow Step 2.
By leveraging this simple yet effective approach, you can elevate the user experience in your model-driven apps, making navigation more intuitive and streamlined for your team.
Special thanks to Kevin Nguyen for showing me how to do this.Let me know how this works for your app or if you have other creative solutions to share!
-

Get the difference between two dates EASY
We have all been there, we need to check the difference between 2 dates, and if you ever had to implement this you would need to use some crazy mathematical equations using the ticks() expression. But now..
I’m not sure when this expression got added, but we can now use dateDifference() expression instead of using ticks().
The dateDifference() expression is a powerful tool in Power Automate and Logic Apps for calculating the difference between two dates.
Allowing to easily determine the number of days, months, or years between two dates, which can be useful in a variety of scenarios.
Syntax and Parameters
The syntax is easy with only 2 parameters:
dateDifference('<startDate>', '<endDate>')
How to Use
Below is a simple example of how to use this expression:
dateDifference('2015-02-08T10:30:00', '2018-07-30T14:45:30')This returns
"1268.04:15:30"
The result is in the format of:
Days.Hours:Minutes:SecondsNote:: If the dates passed in have no time interval, the result shows zeros for the hours, minutes, and seconds. We can extract the different parts of the return by using some expressions inside a Compose action, which we will do next.
Extracting the Result
If you need to extract certain parts of the result into the hours, minutes, or even seconds, you can use the split() expression.
Below you will find the explanation on the extraction, as well as the exact expressions to use.- The
split()function splits the output of dateDifference() at the period (‘.’) into an array with two elements: days and the rest (hours:minutes:seconds). - The
[0]indexer retrieves the first element of the array, which represents the number of days. - The
int()function converts the days from a string to an integer. - Replace the date time values with your dates/time
Extracting Days
To extract the days from the result we can use
int(split(dateDifference('2015-02-08T10:30:00', '2018-07-30T14:45:30'), '.')[0])
This returns:
1268Extracting Hours
To extract the hours interval from the result we can use
int(split(split(dateDifference('2015-02-08T10:30:00', '2018-07-30T14:45:30'), '.')[1], ':')[0])
This returns:
4Extracting Minutes
To extract the minutes interval from the result we can use
int(split(split(dateDifference('2015-02-08T10:30:00', '2018-07-30T14:45:30'), '.')[1], ':')[1])
This returns:
15Extracting Seconds
To extract the seconds interval from the result we can use
int(split(split(dateDifference('2015-02-08T10:30:00', '2018-07-30T14:45:30'), '.')[1], ':')[2])
This returns:
30Things to Know
There are a few things to be aware of:
- Be aware of time zones, Power Automate uses UTC as a baseline for all time formats.
- If pulling dates from SharePoint be aware of what time zone your site is in.
- You can convert the time zones by using expressions or by using actions. Read more about converting time zones here.
Links
date Difference – Reference guide for expression functions – Azure Logic Apps | Microsoft Learn
- The
-

Tip For Testing Your Flows In Power Automate
If your like me, you test your Flows over and over again. This results in sending unwanted emails, creating items in SharePoint or Dataverse, Creating files on OneDrive or SharePoint.
Every time you test your Flow, these actions inside our Flow get executed and cause unwanted behavior when Testing.Wouldn’t it be nice if we can Test our Flows without executing these actions? Guess what we can! And its very easy to do. Check this out!
Scenario
For example, I have a Flow that Create a new row in Dataverse, and then send an email to the person who created the new row. That is fine, but what happens when we have other actions in our Flow that we want to test to make sure they are correct.
I may want to test the Flow multiple times if I am doing some data manipulation, but this will result in Creating multiple unwanted rows (records) in Dataverse, as well as send emails every time.We can clean up the testing process easily.
How?
We can utilize a feature called Static Result.
First click the 3 dots on the action, and select Static Results.

Next we can configure the static results. For easy example click the radio button to enable, select your Status, and the Status Code.

Click Done.
Now the action will have a yellow beaker, indicating that the action is using Static results.

Things to note:
– Static Result are in ‘Preview’ so it could change at any time
– Not all actions will be able to use them
– If the option is greyed out, and you’re certain the action is able to use it, save the Flow and re openThis is only the beginning, as you can create a custom failed response, or create any result you want. This can help troubleshooting and testing certain scenarios.
REMEMBER!! To turn off static results when you want to execute the actions like normal.
Examples
Some examples on when to use static results:
- Flow runs without sending emails
- Flow runs without Approvals needed
- Flow runs that need to test errors on certain actions
- Flow runs testing different error codes (Advanced) + Custom error codes
Conclusion
I have used this feature for awhile now, and noticed not many know about it. It’s so useful in many testing scenarios. Just remember to disable the static results once your done testing!
If you have any questions or want to add anything please leave a comment and like this post! Thank you!
-

How to Use Regular Expressions in Microsoft Power Virtual Agents With Examples
Regular Expressions in Power Virtual Agents? Sounds like a pretty advanced topic. But it’s actually not that difficult and can save you hours of time if you’re trying to validate user input for things such as credit card numbers, tracking IDs, custom invoice numbers or even IP addresses. In this post we’ll cover some of the basics of Regular Expression syntax so you can get started using them inside Power Virtual Agents.
Summary
To utilize regular expressions inside Power Virtual Agents, we must first create a new entity.
This can be be done by clicking the Entities tab > New entity.
Now select Regular expression (Regex)

PVA does a great job in providing some general use case examples.

The syntax is based on .NET
RegEx Examples in PVA
Below you will find some examples you can copy and paste directly into the Pattern for your Regular Expression:
Pattern Description ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ IP Address
– Looks for X.X.X.X format
– Each X range in 0-255
– X length 0-3^4[0-9]{12}(?:[0-9]{3})?$ Visa Credit Card numbers
– Start with a 4
– Old cards use 13 digits
– New cards use 16 digits^3[47][0-9]{13}$ American Express
– Starts with 34 OR 37
– All have 15 digits^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$ Mastercard
Starts with either:
51-55 OR 2221-2720
– All have 16 digits^(?!0{3})(?!6{3})[0-8]\d{2}-(?!0{2})\d{2}-(?!0{4})\d{4}$ Social Security Number
– SSN are 9 digits
– Looks for XXX-XX-XXXX format
– Cannot contain all zeros
– Cannot begin with 666 OR 900-999^[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}$ Mac Address
– 6 byte hex separated by colon “:” OR dash “-”^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$ Port Number
– Matches valid port number in computer network
– 16 bit
– Ranges from 0-65535[A-Z]{2,}-\d+ Jira Ticket Number
– Looks for format Hyphen-separated Jira project key and ticket issue number^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$ Bitcoin Address
26-35 alphanumeric characters
– Start with 1 OR 3 OR bc1^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$ UUID / {guid}
– 36 characters
– 128 bit, represented in 16 octets
– Looks for format form of 8-4-4-4-12Using them in PVA
Once we create the Entity, and define the pattern for our RegEx. We can now use this validation inside our PVA chat.
For example, I will test the IP Address pattern
^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$I have created a topic for testing my RegEx.
To use the newly created entity, Add a Question, under Identify select your Custom Entity

Under this, I add a message to confirm its valid.
(Note, the bot will automatically let the user know if the validation does not match)Testing the RegEx
Okay, drumroll….
The values I will be testing areUser Input Valid? 192.168.1.1 Valid ✔ 127.0.0.1 Valid ✔ 999.55.1.5 Not Valid ✖ Not A IP Address Not Valid ✖ 
Conclusion
Being able to use Regular Expressions inside Power Virtual Agents can be extremely powerful. And with the above list of common patterns, I hope you find value in this post.
Thank you, and have a great day!
-

Check Conditions In Power Automate During Run
The Problem?
Is your Condition not working as expected?
The problem is when we use a Condition action inside Power Automate, we cannot see the “equation” that is being evaluated when looking into the run.The problem affects how we can troubleshoot, the following solution will show what is happening inside the Condition action during the run.
Scenario
In this scenario, I am checking:
If one value is greater than a second value
Now during a test run, I expect to see this condition true, but in my run it is always showing false and going in the If no branch.
The big problem is though, I cannot see what the values being evaluated look like. Take a look below
Clicking on the “Show raw inputs” is also not helpful..

Solution
So what is this quick and easy solution to see the condition results? A simple ‘Compose‘ action.
Lets take a look:
First add a Compose under your Condition
Next copy the values that are in the Condition to the Compose.
My Compose now looks like this:
Now make sure the Compose is above your Condition.
I am just dragging the Condition below the ComposeNext, we can run the Flow again, and see what the Compose can tell us:

Yikes! We can see our 2 values that are being evaluated are both 15.
And 15 is not greater than 15. This is why its returning false.My Thoughts
In my opinion, this should be already visible inside the Condition action. To get this feature added to Power Automate, we can vote on this feature. Head over to the Community Forum and vote for this idea.
View details of Condition results in runs – Power Platform Community (microsoft.com)
The more votes, the better the chances of the Product team implementing this.
Thank you for reading, and have a great day! -

Checking If HTML Table Is Empty In Power Automate
The Problem
I needed to check if an HTML table had data or not. Usually when I need to check I have two expressions I go to first.
- empty()
- length()
I tried using empty() and found that the HTML table even when empty, is not truly empty.
I then tried length() and found that when the HTML table is empty there is still a length of 30.The Scenario
I have some data that is used to track different devices that can be loaned out. The data has properties like, Type of device, Serial Number, Etc.
The data comes in, and looks like this:
[
{
"type": "Phone",
"device": "iPhone 11 Pro",
"serialNumber": "0007488"
},
{
"type": "Phone",
"device": "Samsung Galaxy S20",
"serialNumber": "1166289"
},
{
"type": "Watch",
"device": "Apple Watch Series 5",
"serialNumber": "00013701"
},
{
"type": "Laptop/Tablet",
"device": "Surface Pro X",
"serialNumber": "AA78442"
}
]I want to put this array of data inside a HTML table and send it out on an email. The problem is, my data might be empty, as only available devices will show up in my data.
I need to check if the HTML table is empty, if it is empty:
If True:
Send email with HTML table
If False:
Send email without HTML tableThe Flow
For this Flow, I will be using an Array Variable to simulate my data coming in from another system.
I will call this Variable ‘Data‘.
The HTML table action will be added underneath.
You will need to determine if you want to use ‘Custom columns‘ or ‘Automatic columns‘ This can be done in the advanced options in the HTML action:
My ‘Data‘ Variable is empty at the moment. This is what we want for our first run, we want to get the length of the HTML table when its empty.
Next add a ‘Compose‘ action, and use the expression length(), pass in the HTML table as the parameter. For example, my expression looks like:
length(body('Create_HTML_table'))
Now run the Flow with no Data in the HTML table, and check your Compose action to see what the length is. In my case it is 30

Now we can add a If Condition to check if the length is greater than 30
** TIP **
I am passing in the Compose action into the condition, this allows me to see what the outputs of the Compose action before it gets evaluated inside the condition. This is extremely useful for troubleshooting
Conclusion
The Flow will go into the ‘If yes’ block if the HTML table has data

The Flow will go into the ‘If no’ block if the HTML table is empty

Of course checking the Data Variable itself for length could work way better. This example is mainly for data that can come in that could have loads of junk. For example:
An HTTP API could bring in no data, but still have other information attached like, headers, status code, version. In this case we can only do conditional checks on the HTML table, since our Data variable will always have something being passed in.I used this method to help someone on the Community Forum, check it out here:
https://powerusers.microsoft.com/t5/Building-Flows/Create-a-Flow-with-Condition-that-does-not-send-email-when-list/m-p/721076/highlight/false#M98488



























