@aaileni -
Hereâs a practical, way to (1) normalize those strings to ISO-8601 and (2) check if theyâre older than X daysâusing either an Identity Profile transform (Account Attribute) or a Workflow » Define Variable step.
1) Normalize to ISO-8601 (Account Attribute transform)
Your inputs vary by locale and hour notation and always end with UTC, e.g.:
-
4/11/2025 16:19:51 PM UTC â” malformed (24-hour + AM/PM together)
-
4/1/2025 6:19:51 AM UTC â” US style, 12-hour + AM/PM
-
14/11/2025 16:19:51 AM UTC â” malformed (24-hour + AM/PM), day-first
SailPointâs dateFormat needs a single input pattern per attempt. Use firstValid to try multiple patterns and output ISO-8601. (It uses Java SimpleDateFormat tokens and supports the literal timezone via z.) (Date Format)
Account attribute transform (example):
{
"name": "NormalizeLastSeenToISO",
"type": "firstValid",
"attributes": {
"values": [
{
"name": "US_12h_AMPM",
"type": "dateFormat",
"attributes": {
"input": { "type": "accountAttribute", "attributes": { "sourceName": "My Source", "attributeName": "rawLastSeen" } },
"inputFormat": "M/d/yyyy h:mm:ss a z",
"outputFormat": "ISO8601"
}
},
{
"name": "US_24h",
"type": "dateFormat",
"attributes": {
"input": { "type": "accountAttribute", "attributes": { "sourceName": "My Source", "attributeName": "rawLastSeen" } },
"inputFormat": "M/d/yyyy HH:mm:ss z",
"outputFormat": "ISO8601"
}
},
{
"name": "DMY_12h_AMPM",
"type": "dateFormat",
"attributes": {
"input": { "type": "accountAttribute", "attributes": { "sourceName": "My Source", "attributeName": "rawLastSeen" } },
"inputFormat": "d/M/yyyy h:mm:ss a z",
"outputFormat": "ISO8601"
}
},
{
"name": "DMY_24h",
"type": "dateFormat",
"attributes": {
"input": { "type": "accountAttribute", "attributes": { "sourceName": "My Source", "attributeName": "rawLastSeen" } },
"inputFormat": "d/M/yyyy HH:mm:ss z",
"outputFormat": "ISO8601"
}
}
]
}
}
This yields a clean ISO8601 value like 2025-11-04T16:19:51.000Z in the profile mapping.
If a source actually produces â16:19:51 PMâ (24-hour + AM/PM), that is an invalid timestampâno dateFormat pattern can correctly interpret it. Fix upstream to either HH:mm:ss z without a, or h:mm:ss a z with a 1â12 hour. (The transform docs require pattern/data agreement.) (Date Format)
2) âOlder than X days?â in a Workflow (Define Variable)
dateCompare requires both sides in ISO-8601. Weâll compute threshold = now â X days via dateMath, then compare. dateMath accepts now and outputs yyyy-MM-dd'T'HH:mm; so we wrap it with a small dateFormat to standard ISO-8601 before comparing. (Date Math)
Define Variable â âthresholdISOâ (Transform):
{
"name": "thresholdISO",
"type": "dateFormat",
"attributes": {
"input": {
"name": "NowMinusXd",
"type": "dateMath",
"attributes": {
"expression": "now-{{ steps.input.variables.XDays }}d",
"roundUp": false
}
},
"inputFormat": "yyyy-MM-dd'T'HH:mm",
"outputFormat": "ISO8601"
}
}
- Set
XDays as a preceding Workflow Input (number), or hardcode e.g. now-30d.
Define Variable â âisOlderThanXDaysâ (Transform):
{
"name": "isOlderThanXDays",
"type": "dateCompare",
"attributes": {
"firstDate": {
"type": "identityAttribute",
"attributes": { "name": "NormalizeLastSeenToISO" }
},
"secondDate": {
"type": "identityAttribute",
"attributes": { "name": "thresholdISO" }
},
"operator": "LTE",
"positiveCondition": true,
"negativeCondition": false
}
}
- Returns boolean. Use it directly in a Condition step (e.g., route notifications, disable accounts, etc.).
dateCompare supports LT/LTE/GT/GTE and accepts "now" too, but here we compare to a computed threshold. (Date Compare)
Variants you might need
-
Working directly off an Account Attribute in Workflow
If you donât want to map an identity attribute, you can replace "identityAttribute" above with a nested firstValid+dateFormat that reads the account attribute using JSONPath in a Transform variable, then feed that normalized ISO-8601 into dateCompare.
-
Define Variable built-ins
Workflows also provide date operators like Add Time in âDefine Variableâ, but theyâre limited (†1 year from original date) and donât help with parsing non-ISO inputs. The transform approach is more robust for mixed formats. (Define Variable in ISC Workflow)
Quick testing tips
-
Start by echoing the raw and normalized values in a test run (Log step).
-
Verify a couple of edge dates around the threshold (e.g., exactly X days, X+1).
-
If any feed still shows â16:⊠PMâ, fix the producer or pre-normalize upstream (e.g., switch to HH:mm:ss z without AM/PM).
References
Cheers!!!