The symptom
A 21-day call-pattern analysis produced “peak hour” results that were off by a fixed, deterministic amount. That pattern always means time zones.
The cause
Casting an ISO datetime string with an embedded offset to [datetime] in PowerShell converts it to the machine’s local time zone, not the one in the string. Depending on where your automation runs and where your customer is, that’s a 2–8 hour shift.
The fix
Use [datetimeoffset]::Parse() for anything that aggregates by hour of day or day of week. It keeps the original offset.
It showed up twice
The same pattern, UTC midnight instead of the customer’s local midnight, also turned up in a production runbook’s pull window. I added an explicit -LocalDate parameter.
Bonus: Azure Automation doesn’t know what time zone it’s in
Inside the PowerShell 7.2 sandbox, FindSystemTimeZoneById() fails for every ID, IANA or Windows, because the sandbox runs in invariant globalisation mode. The error message echoes back the exact ID you passed, so it looks like a typo. The fix was a fixed-offset lookup table.
Takeaway
Any report claiming “peak time X” needs an explicit time-zone test, not an assumption.