Sunday, March 25, 2012

MSCRM 2011 using whole number time zone format for parsing date time sting C#

MSCRM 2011 using whole number time zone format for parsing date time sting


Multi-international companies, often needs to take care of time zone in date time fields coming from outer systems. It gets complicated when the time zone isn't part of the date time string.
In this example I've create new whole number attribute in time zone format named new_timezone.
I've used it for translating the date time string to the right UTC date time with taking care of the day light saving.


The Idea.
1) Getting the time zone code (int) from the time zone attribute (whole number - time zone format)
2) Getting the MSCRM TimeZoneDefinition entity matching the time zone code
3) Using the MSCRM TimeZoneDefinition for getting .net TimeZoneInfo (by comparing the standard name).
4) Parse the Date Time string to DateTimeOffset.
(Thanks http://stackoverflow.com/questions/5615538/parse-a-date-string-into-a-certain-timezone-supporting-daylight-saving-time for the method)
5) Update the relevant attribute with UTC date time.


The code (C# - originally used in plugin):

//accTemp = Is account entity with time zone attribute
//GetEntityByName = is function getting the matching entity by comparing attribute to a value


//Get timezone info from account
TimeZoneDefinition timeZoneTemp;
//accTemp.new_timezone
if (accTemp.new_timezone != null)
{
        Entity timeZoneEntityTemp = GetEntityByName(localContext.OrganizationService, TimeZoneDefinition.EntityLogicalName, "timezonecode", accTemp.new_timezone.Value.ToString());
         if (timeZoneEntityTemp != null)
        {
              timeZoneTemp = timeZoneEntityTemp.ToEntity<TimeZoneDefinition>();
         }
}


//parse the datetime by account timezone
TimeZoneInfo tz = GetTimeZoneInfoByStandardName(timeZoneTemp);
string dateString = String.Format("{0} {1}",  anyEntity.new_dateString,  anyEntity.new_timeString);
DateTimeOffset dtOffset = ReadStringWithTimeZone(dateString, tz);
DateTime  dt =  dtOffset  .UtcDateTime;

anyEntity.new_datetime= dt;


public TimeZoneInfo GetTimeZoneInfoByStandardName(TimeZoneDefinition timeZoneTemp)
        {
            var timezonesInfo = TimeZoneInfo.GetSystemTimeZones();
            foreach (var timezone in timezonesInfo)
            {
                if (timezone.StandardName == timeZoneTemp.StandardName)
                {
                    return timezone;
                }
            }
            throw new Exception(String.Format("Internal Exception: Fail to get TimezoneInfo: Standard Name = {0}, TimeZone Code = {1}", timeZoneTemp.StandardName, timeZoneTemp.TimeZoneCode));
        }

public DateTimeOffset ReadStringWithTimeZone(string EnteredDate, TimeZoneInfo tzi)
{
      try
     {
            DateTimeOffset cvUTCToTZI = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi);
            DateTimeOffset cvParsedDate = DateTimeOffset.MinValue;
            DateTimeOffset.TryParse(EnteredDate + " " + cvUTCToTZI.ToString("zzz"), out cvParsedDate);
                if (tzi.SupportsDaylightSavingTime)
                {
                    TimeSpan getDiff = tzi.GetUtcOffset(cvParsedDate);
                    string MakeFinalOffset = (getDiff.Hours < 0 ? "-" : "+") + (getDiff.Hours > 9 ? "" : "0") + getDiff.Hours + ":" + (getDiff.Minutes > 9 ? "" : "0") + getDiff.Minutes;
                 DateTimeOffset.TryParse(EnteredDate + " " + MakeFinalOffset, out cvParsedDate);
                  return cvParsedDate;
                }
                else
                {
                    return cvParsedDate;
                }
       }
       catch(Exception ex)
       {
             throw new Exception(String.Format("Fail to parse date time: {0}", EnteredDate), ex);
       }
}

Hope it helps.


Any other ideas? Have better solution for the problem? Please share them...



No comments:

Post a Comment