We are trying to compare two date strings in an Architect expression to filter records. The documentation suggests using DateTimeDiff, but it consistently returns null. We have verified the input format is ISO 8601.
DateTimeDiff('{{contact.data.created_date}}', '{{current_time}}', 'day')
Is there a specific parsing requirement we are missing? The logs show no syntax errors.
2 Likes
The parser in Architect expects actual date objects. Do not pass raw strings directly. Even with ISO 8601, the engine usually drops the value to null. Try wrapping the contact field in DateParse first. Something like DateParse('{{contact.data.created_date}}', 'yyyy-MM-ddTHH:mm:ss') before feeding it into DateTimeDiff. This is a reliable workaround we apply across our multi-org setup. Config exports between staging and prod often break when environment variables shift the time format. I have referenced several community posts regarding this config promotion issue. If you are just looking for a boolean filter, DateTimeCompare is actually lighter on the engine. It skips the math entirely. Just swap the function and keep the same inputs. Make sure both sides share the exact same timezone offset too, otherwise the system defaults to UTC and throws off the result. In our Europe/Berlin timezone configuration, offset mismatches frequently cause staging/prod drift. Check the expression builder validation tab before saving. The logs won’t catch type mismatches anyway. This validation step is essential for clean CX as Code pipelines and org comparison.
1 Like
The Architect expression engine is painfully strict on data types, and feeding raw strings to DateTimeDiff guarantees a null return. Both Current_Time and the incoming timestamp are just strings until explicitly converted, so you have to force them through DateParse with the exact format pattern, or the parser drops it instantly. This constantly breaks Queue Filtering logic when source systems tweak the timestamp format, and Environment Variables shifting between Staging and Prod wreck the format expectations, leaving Dashboard Widgets blank. I prefer managing the Admin UI layout and queue analytics, but the Admin UI never flags these type mismatches clearly, so you’re stuck digging through logs. Wrap both inputs in DateParse with the precise pattern. For standard ISO 8601 with Milliseconds and Timezone, the pattern must be exact. Here is the working syntax for the Expression Builder:
DateTimeDiff(DateParse('{{contact.data.created_date}}', 'yyyy-MM-ddTHH:mm:ss.SSSZ'), DateParse('{{current_time}}', 'yyyy-MM-ddTHH:mm:ss.SSSZ'), 'day')
If the source date lacks Milliseconds, strip the .SSS or it fails silently. Verify the output in the Expression Evaluator before saving the flow, because the UI will happily accept invalid syntax until runtime, wasting hours debugging broken queue scripts. Ensure the Created_Date attribute is actually populated, since empty attributes just return nulls. The Timezone offset Z also breaks things if the source pushes +00:00, so test with a static value first. This normalization directly impacts how interaction history sorts in the Agent Desktop. Check the Attribute Definition to confirm it’s set to a Date Type, not Text Type.
The previous suggestion is accurate. You’re piping unformatted strings straight into DateTimeDiff and expecting implicit type coercion. Architect’s expression engine doesn’t auto-parse like Twilio’s <Value> tags do. You must explicitly cast both operands. {{current_time}} outputs a raw UTC string, not a native date object, which causes the diff evaluator to fail immediately.
Wrap both operands in DateParse and align the format mask with your source payload. If created_date originates from a webform submission or a Data Action response, it’s almost certainly yyyy-MM-dd'T'HH:mm:ss'Z'. This is the valid syntax for the expression builder:
DateTimeDiff(DateParse('{{contact.data.created_date}}', 'yyyy-MM-dd''T''HH:mm:ss''Z'''), DateParse('{{current_time}}', 'yyyy-MM-dd''T''HH:mm:ss''Z'''), 'day')
Note the single-quote escaping around T and Z. Omitting them forces the parser to treat them as literal characters, yielding null. We encountered this exact failure mode while migrating a Twilio Studio flow that depended on native JavaScript Date objects. Architect’s expression evaluator enforces strict type coercion. Alternatively, bypass the string-parsing overhead entirely by offloading timestamp normalization to a Data Action. Deploy a lightweight Node.js endpoint executing Math.floor(new Date(input).getTime()) to return a Unix epoch. Then invoke DateTimeDiff('{{contact.data.created_epoch}}', '{{current_epoch}}', 'second'). This sidesteps the expression builder’s rigid date format regex entirely.
Inspect the expression evaluation trace in your flow logs. Retrieve the raw execution payload via GET /api/v2/analytics/flows/flowlogs?filter=flowId:{{flow_id}}&fromDate=2024-01-01T00:00:00Z or programmatically through the PureCloudPlatformClientV2 SDK using platformClient.FlowLogs.getFlowFlowlogs(...). If the evaluator still returns null, your source timestamp contains a trailing whitespace. Prepend Trim() to the input before passing it to DateParse. Source systems frequently append fractional seconds that violate the format mask and break the regex match.
The null return happens because the Architect expression engine doesn’t auto-cast ISO 8601 strings into temporal objects. It treats them as plain text until a parser explicitly converts them. When both sides stay as strings, the diff function just bails out. I’m still pretty new to this whole GC + middleware stack, but here’s a methodical way to patch the flow without breaking the pipeline:
- Wrap the contact field in
DateParse first. Match the pattern exactly to what the Kafka stream spits out. DateParse('{{contact.data.created_date}}', 'yyyy-MM-ddTHH:mm:ss.SSSZ')
- Run
{{current_time}} through the same parser. The system variable defaults to a UTC string, so leaving it raw guarantees a type mismatch.
- Add a fallback null check. Architect drops the whole expression if one side fails to parse, so wrapping it in
IfNull(..., 0) keeps the logic from stalling.
- Check the webhook payload schema. Sometimes the source API strips the timezone offset, which breaks the strict parser. A quick Java SDK test with
OffsetDateTime.parse() usually catches that before it hits the flow.
Sorry for the newbie question, but does the expression engine cache the parsed values across steps, or does it re-run the conversion every time? The documentation isn’t super clear on that. I’m still wrapping my head around how the GC Java SDK handles webhook processing and API rate limit handling, so I’m not sure if this is expected behavior. Just throwing this out there since similar type mismatches pop up constantly in MuleSoft routes.
1 Like