Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics CRM (Archived)

SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

Posted on by Microsoft Employee

I made a very simple program to demonstrate the problem as simply as possible to myself, and eliminate as many variable as possible.

it connects to Crm with a given user, lets say: bob 

bob's timezone is set to CET (currently 2+ offset from UTC as its summer time)

my own computer, where the program runs is also set to CET.

My program does the following:

  • as bob, it retrieve a entity
  • it fills a datefield on the entity like so: entitie["datefield"] = DateTime.now 
  • update entity back to CRM.
  • and retrieve entity again from CRM and checks the date (the raw UTC value, not the formatted one) 

The date is now not the expected 2 hours behind local time, but 4 hours.

The value displayed to the user is therefor 2 hours behind what's expected.

  • Changing bobs timezone in CRM to +4 (Baku) and running the program again:

results in 6 hours offset instead of 2

  • Setting my computer timezone to +8 (Beijing):

Results in a offset of 12 instead of 2.

so it seems to apply both the local computer's offset where the code runs, AND the user's configured timezone's offset!

I can understand it adjusting for either the PC's local time, OR the users timezone, either one would have made at least some sort of sense.

but not both right?

Can anyone help me and explain whats going on? And is there a way to save local time and have it end up correct? (We do this extensively throughout or code it would be a time consuming to adjust it all) 

our on premise installation doesn't have this problem, despite both the user and the server being set to CET.

Crm: (versie 1612 (8.2.2.1259) (DB 8.2.2.339) online)

SKD/DLL version used 8.2.0 (nugets)

(side note: saving the time as entitie["datefield"] = DateTime.UtcNow always gives the correct result.)

*This post is locked for comments

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    That doesn't explain why the behavior is different between on-prem and on-line

    and certainly doesn't explain why the behavior we see, (even with different customers tenants!) is different then what Wei Jie Fun gets in the video.

    So far the only thing that's worked consistently, both on-line and on-prem, is converting any and all dates to UTC time before saving into CRM.

    But its annoying, we deal with a lot of date fields, and receive data from a wide range of sources, and it use to work perfectly fine on prem.

    But now suddenly we have to go over all our code to convert dates to UTC time before saving. We've already had a lot of gotha's were the conversion was missing, or we forgot to add it to new functionality.

  • Suggested answer
    kyleknab Profile Picture
    kyleknab 517 on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    "But i still don't understand why a datetime with its kind set to local is converted twice."

    DateTime operations through the CRM SDK will always be assumed, by CRM, to be passed with a UTC value, regardless of its DateTimeKind. It converts(1) the assumed-UTC object to an object in your configured timezone, and then it reads the DateTimeKind and if it finds 'Local' it converts the object again(2) to UTC.

    The .NET DateTime object doesn't have knowledge of a timezone offset property and CRM cannot guess what timezone the machine running your custom client application was in when it generated the DateTime.Now  object (which is local to the machine, not the CRM user) and sent the SDK request.

    DateTime.UtcNow (or some equivalent) fits CRM's assumptions because it's universal!

    Member name and value

    Description

    UserLocal

    • Stores the date and time value as UTC value in the system.

    • The retrieve operation returns the UTC value.

    • The update operation converts the UTC value to the current user’s time zone value, and then stores the updated value as is or as the equivalent UTC value depending on the kind (DateTimeKind) of the value specified for update. If the specified value is of UTC kind, it’s stored as is. Otherwise, the UTC-equivalent value is stored.

    • Retrieving the formatted value converts from UTC to the user’s current time zone based on the time zone and locale setting of the user.

    • For the OData endpoint, the attribute is exposed as DateTimeOffset.

    • This behavior is used for system attributes like CreatedOn and ModifiedOn, and cannot be changed. You should use this behavior for custom attributes where you want to store date and time values with the time zone information.

    DateOnly

    • Stores the actual date value with the time value as 12:00 AM (00:00:00) in the system.

    • For the retrieve and update operations, no time zone conversion is performed, and the time value is always 12 AM (00:00:00).

    • Retrieving the formatted value displays the date value without any time zone conversion.

    • For the OData endpoint, the attribute is exposed as DateTimeOffset.

    • This behavior should be used for custom attributes that store birthdays and anniversaries, where the time information is not required.

    TimeZoneIndependent

    • Stores the actual date and time values in the system regardless of the user time zone.

    • For the retrieve and update operations, no time zone conversion is performed, and actual date and time values are returned and updated respectively in the system regardless of the user time zone.

    • Retrieving the formatted value displays the date and time value (without any time zone conversion) based on the format as specified by the current user’s time zone and locale setting.

    • For the OData endpoint, the attribute is exposed as DateTimeOffset.

    • This behavior should be used for attributes that store information such as check in and check out time for hotels.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    The user's timezone on portal.office.com is also set to CET, but changing it doesn't change anything in the behavior.

    I haven't been able to find a tenant wide timezone setting. Is there one?

    results so far:

    • Another computer: no difference,
    • Created a new entity and datefield (exactly as on your picture): no difference
    • Completely Different tenant: same behavior
    • creating a new DateTime object from a string, or specifying the digits: works!

    Basically any DateTime object with it's 'kind' set to unspecified (as opposed to utc or local) works exactly as i would expect it to.

    Its time value is my local time, and once saved its the Utc equavalent. With unspecified it only takes into account The users timezone as set in CRM, and ignores the timezone of the machine running the code.

    To get the equivalent of DateTime.now i can use new DateTime(DateTime.Now.Ticks, DateTimeKind.Unspecified);

    But i still don't understand why a datetime with its kind set to local is converted twice.

  • Alex Fun Wei Jie Profile Picture
    Alex Fun Wei Jie 33,626 on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    Hi,

    is your online tenant under different regions ?

  • Temmy Wahyu Raharjo Profile Picture
    Temmy Wahyu Raharjo 2,914 on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    Hi Vincent,

    For DateTime, I suggest you to always use DateTime.UtcNow instead of DateTime.Now. It will eliminates problem with different region.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    Thanks for the video, couldn't be clearer, and that's the behavior i would expect. And in fact what i get on our on-premise environments. but not online. all 3 our online instances show the same behavior.

    That's so weird!

    The only differences in the date time settings are that auditing is disabled and IME mode is set to inactive.

    Neither one of which should have any effect on this that i can tell.

    At the very least i now know its something on our end and not normal Crm online behaviour.

    Tomorrow i'll see if i can try a different tenant/organisation and try the program from a different computer,

    and i'll try to update the SDK files as well.

    Thank you for the help so far, i'll keep you posted on the results.

  • Alex Fun Wei Jie Profile Picture
    Alex Fun Wei Jie 33,626 on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    Hi,

    sorry for late, in my environment, it is working fine, is the date time setting same as yours?

    2086.7.png

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    sure, it's in Dutch so i'll have to translate.

    required: optional

    searchable: yes,

    fields security: disabled

    checks: disabled

    interactive: both not checked)

    datatype: date and time

    fieldtype: simple

    behavior: usersetting

    format: date and time

    IME-modus: inactive

    and there are no business rules defined.

  • Alex Fun Wei Jie Profile Picture
    Alex Fun Wei Jie 33,626 on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.

    Hi,

    can you show me the datefield setting in CRM ?

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: SDK/C# Timezone offset applied twice when saving a local time into a datetime field on CRM online.
    Sure thing, and thank you for taking the time. 


    //boilderplate var credentials = new ClientCredentials(); credentials.UserName.UserName = userName credentials.UserName.Password = Password; string xrmServerUrl = "ourserver.crm4.dynamics.com"; Uri organizationUri = new Uri(string.Format("{0}/XRMServices/2011/Organization.svc", xrmServerUrl)); var organizationService = new OrganizationServiceProxy(organizationUri, null, credentials, null); organizationService .EnableProxyTypes(); //boilderplate //get entity var entity = organizationService.Retrieve("entityLogicalName", new Guid("C2EA1587-0731-E811-813F-00DC2967EB29"), new ColumnSet(true)); //set date field entity["datefield"] = DateTime.Now; //update organizationService.Update(entity); //retrieve updated entity, entity = organizationService.Retrieve("entityLogicalName", new Guid("C2EA1587-0731-E811-813F-00DC2967EB29"), new ColumnSet(true));
    //read the date
    var date = (DateTime)entity["datefield"];


    with both the user's timezone in CRM and the computer running the code set  to CET (2+ in summer time)

    and i do this at 16:00,

    i would expect the date at the end to contain a UTC datetime of 14:00

    but it's actually 12:00!

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,280 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,214 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans