Once upon a time server-side connections to Dynamics 365 / CRM were easy. Use username and password to connect and, if you are license-conscious, use non-interactive account. Users have timezones that can be set using personal options (for non-interactive, logon after assigning the license but before converting to non-interactive, and set the zone). The day you decide to use application user instead, is a good day in my books but be prepared for some surprises if your code expects the service account to be in a specific timezone (as we discovered on one of the migration projects). You actions will depend on what and how service account is used.
Easy way out
If you find that the tests fail, the code breaks, and the times are off, you can quickly apply the bandage solution – set the timezone for the application user (by default it’s UTC). You could do it programmatically, but User Settings utility in XrmToolBox will do the job.
Fix it (kind of)
When you retrieve datetime fields from Dynamics 365, SDK methods (e.g. entity.GetAttributeValue<DateTime>("datefield")
) will return UTC value regardless what timezone is set for your service account. There must be a reason why your code relies on the timezone of the service account but if it does, you can use Daryl “Always Raising” LaBar‘s GetUserTimeZone sample code and do something like
var tzInfo = GetUserTimeZone(service, serviceUserId); var utcValue = entity .GetAttributeValue<DateTime>("datefield"); var locaValue = TimeZoneInfo .ConvertTimeFromUtc(utcValue, tzInfo);
Do it properly
Whatever is the reason for relying on the timezone of your service account, it must be related to some UI shenanigans otherwise it begs the question if it’s appropriate (Scenario 4 is an exception). If it is UI-related (e.g. displaying something on the website) then you shouldn’t be using timezone of the service account but instead:
- Scenario 1. User is authenticated Dynamics 365 user (think intranet scenarios). Impersonation is the way to go, use GetUserTimeZone above. Quick reminder: WhoAmI is not your friend here.
- Scenario 2. User is authenticated portal user (extranet scenarios). In this case, user (contact) record would have a timezone field describing user’s locale/preference.
- Scenario 3. User is anonymous. That’s a tricky one. You would either nail the timezone (where we, the website, are) or derive it from the browser (where the browser, i.e. the client, is). For the latter you’d have to use some javascript as well – there is no way to
deriveguess a browser timezone or locale using server-side only code. - Scenario 4. No UI, pure server-side, e.g. for integration purposes. Ideally, you’d pass UTC datetime values but if for some reason the other party expects a specific timezone, your best bet would be to have an independent setting that describes the expected target timezone.
In short, there is no reason to rely in your code on the timezone of the service account. Find those dependencies and get rid of them.
(Facebook and Twitter cover photo by Luis Cortes on Unsplash)
A common need for needing dates in the users time zone is to calculate elapsed business days between two events. The difference between two UTC dates might tell you how many 24 hour periods elapsed but not how many actual days.