A very common nightmare for everyone whose business requirements deals with date time fields is how to retrieve user’s local time zone date time values from CRM database. This becomes significant when our organization is widespread globally and there are different users in our organization working for different time zones across the globe.
Remember, if you are writing a plugin to retrieve date time field, we receive it in UTC format. However, if you try to write to CRM server, you need to manually convert the time into UTC time zone and store in CRM database (CRM by default wont convert the input time to UTC format). You might raise an objection saying we can easily convert any date time into UTC time zone by using some default .NET functions like DateTime.UtcNow inside a plugin. But the main problem occurs when we want to perform vice versa operation i.e converting a UTC time to users local time zone or if we want to find the present date time of user under whose context plugin is running. We are thus handicapped from using a generic UtcNow function. If you are using CRM online, then plugins will be deployed into CRM server. Microsoft does have different data centers and based on the time zone in which your CRM server is hosted, my plugin runs in that time zone and the date time value retrieved belongs to that time zone.
What if the plugin is run on users context? Since we have users in different time zones across the globe, and our CRM server in which plugin runs is hosted in one particular time zone, more care needs to be taken which retrieving date time values and converting them into user’s local time zone. For example, my CRM server is hosted in CST (central standard time -4:00 UTC) and we have plugin running under an users context whose time zone is IST (Indian standard time +4:30 UTC). If I try to retrieve present date time from my C# plugin, I will get current CST time not IST because my plugin is running under CST zone though the user is logging from IST.
Therefore, there is a need to discover some mechanism to get present date time of user’s context (IST) rather than CRM servers context (CST). Fortunately, we have 2 functions available in CRM SDK to meet our requirement.
At First, we have to retrieve users time zone code. Every time zone has a unique code (2 digit or 3-digit number). The function is:
private static int? RetrieveCurrentUsersTimeZoneSettings(IOrganizationService service) { var currentUserSettings = service.RetrieveMultiple( new QueryExpression("usersettings") { ColumnSet = new ColumnSet("localeid", "timezonecode"), Criteria = new FilterExpression { Conditions = { new ConditionExpression("systemuserid", ConditionOperator.EqualUserId) } } }).Entities[0].ToEntity<Entity>(); return (int?)currentUserSettings.Attributes["timezonecode"]; }
This function will return a time zone code based on the user’s time zone in his personal settings. It is very easy to get the present UTC time no matter in which time zone we are using DateTime.UtcNow() function. We need to pass the UTC time, time zone code to another function which will return the user time zone’s date time equivalent to UTC time.
private static DateTime? RetrieveLocalTimeFromUTCTime(IOrganizationService _serviceProxy, DateTime utcTime, int? _timeZoneCode) { if (!_timeZoneCode.HasValue) return null; var request = new LocalTimeFromUtcTimeRequest { TimeZoneCode = _timeZoneCode.Value, UtcTime = utcTime.ToUniversalTime() }; var response = (LocalTimeFromUtcTimeResponse)_serviceProxy.Execute(request); return response.LocalTime; }
In this way we can easily calculate the users local time at any moment once we know the UTC time (which is pretty easy to find using DateTime.UtcNow() function inside a plugin) and users time zone code inside a plugin.
*This post is locked for comments