Tuesday, February 21, 2012

Get the Entity Data based on user time zone

If your CRM application is used by multinational users, and if you have custom web pages or any client applications, you have to make sure you show the date and time with the user's time zone, rather than just showing the value you get by retrieving from the CRM Service.
I have below described an easier method to do so.

First we have to get the current user's time zone.
And then let's retrieve the entity object from the CRM Service.
Then we can call our method that will adjust all the DateTime properties in the CRM entity.
public partial class SystemUser
{
    RetrieveUserSettingsSystemUserResponse userSettingsSystemUserResponse;

    /// 
    /// Initialize RetrieveUserSettingsSystemUserResponse
    /// 
    private void InitializeUserSettings()
    {
        if (this.Id != Guid.Empty)
        {
            RetrieveUserSettingsSystemUserRequest userSettingsSystemUserRequest = 
                new RetrieveUserSettingsSystemUserRequest { 
                  RequestId = this.Id,  ColumnSet = new ColumnSet(true),  EntityId = this.Id };

            userSettingsSystemUserResponse = (RetrieveUserSettingsSystemUserResponse)CrmServiceManager
                          .GetService(this.Id).Execute(userSettingsSystemUserRequest);
        }
    }

    /// 
    /// Get a date and returns it back adjusting TimeZone difference
    /// 
    public DateTime GetUserTimeZoneBasedDateTime(DateTime dateTime)
    {
        if (this.Id != Guid.Empty)
        {
            if (userSettingsSystemUserResponse == null)
            {
                InitializeUserSettings();
            }

            if (userSettingsSystemUserResponse != null 
                && userSettingsSystemUserResponse.Results != null 
                && userSettingsSystemUserResponse.Results.Count > 0)
            {
                return dateTime.AddMinutes(
                     ((UserSettings)userSettingsSystemUserResponse.Entity).TimeZoneBias * -1);                    
            }                
        }

        return dateTime;
    }
        
    /// 
    /// Get the Entity and returns it back adjusting TimeZone difference
    /// 
    public T GetEntityWithUserTimeZoneBasedDateTime<t>(T t) where T : Entity
    {
        if (t != null)
        {
            Dictionary<string, Datetime> changedDateTimeDictionary = new Dictionary<string, Datetime>();
            foreach (var attribute in t.Attributes)
            {
                if (attribute.Value is DateTime)
                {
                    changedDateTimeDictionary.Add(
                         attribute.Key, GetUserTimeZoneBasedDateTime((DateTime)attribute.Value));
                }
            }

            foreach (var item in changedDateTimeDictionary)
            {
                t.Attributes[item.Key] = item.Value;
            }
        }

        return t;            
    }
And now you can call the method as below

Guid currentUser = //Set the current user

//Get the record from CRM Service using any convinient method
Account account = new CommonFacade().Get<account>(accountId);

//Pass the retrieved object and with the current user
//That adjust the all DateTime properties in the object
//And reassigned it before displaying the entity

account = new SystemUser {Id = currentUser }.GetEntityWithUserTimeZoneBasedDateTime<account>(account);

//Now you can use the object to any display purposed
//Example
accountCreatedOnLabel.Text = account.createdOn.ToString();

3 comments:

  1. Hi Jude,

    Guess it doesn't take care of Daylight Saving time, I tried this but doesn't seem to work with Current British Summer Time.

    Thanks

    V

    ReplyDelete
  2. Thanks for the interesting info, but yes it seems we need also add TimeZoneDaylightBias to get the correct result:)

    ReplyDelete
  3. Hello,

    Thanks for pointing this. Yes we have to add the TimeZoneDayLightBias as well.

    ReplyDelete