Bug 23580 - Passing a NSDate a DateTime value with DateTimeKind Unspecified treats as if Local
Summary: Passing a NSDate a DateTime value with DateTimeKind Unspecified treats as if ...
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 8.0.0
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-10-03 09:48 UTC by Neal
Modified: 2014-10-21 15:07 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
NSDate from DateTime example app (9.12 KB, application/zip)
2014-10-03 09:48 UTC, Neal
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Neal 2014-10-03 09:48:39 UTC
Created attachment 8297 [details]
NSDate from DateTime example app

Hello,

I ran into a situation recently where I assigned a NSDate property a DateTime value coming from a WCF DTO where DateTime values come across as DateTimeKind.Unspecified.  We have to use the NSDate property due to CoreData implementation and I got an unexpected result mainly from realizing the handling of DateTime to NSDate.  This may be by design but I'd like to discuss the scenario...

In a test I attached you can see I am creating three DateTime values for each DateTimeKind. I'm then assigning these values directly to NSDate fields to see how Xamarin converts them automatically.  I then assign the output to the view by returning a DateTime that reads back the NSDate field value.

What I have found is that your NSDate conversion treats DateTimeKind unspecified as Local.  I believe C# .NET actually does the opposite and assumes UTC or quite frankly doesn't make any conversion.  This has been important in the past with DataSets prior to DTO's as the DataSet would pass converted data.  But I digress...

Long story longer I got an unexpected result because I assigned a DateTime value to a NSDate property which converted it unexpectedly.  I corrected my code by setting the DateTime property available instead and that solved the problem but it opened my eyes to this situation.  The problem as I see it is the vulnerability of someone passing a DateTime to NSDate and Xamarin handling the conversion with false assumptions.  In my opinion, I'd like to prevent Xamarin from converting DateTime to NSDate so we are forced to handle this manually and not get an unexpected result.  Or maybe Xamarin can throw a message somewhere if it receives a DateTimeKind Unspecified as you're making a wrong assumption on how the date is to be converted.  If you get DateTimeKind local that's a given you know how to process that, if you get DateTimeKind Utc then you have that, but how you're handling DateTimeKind Unspecified I believe needs review to prevent errors like I caused.

I hope this explains the scenario with the test case attached.  I look forward to your feedback on how to prevent this in the future.

Thank you.

Neal Culiner
NC Software, Inc.
Comment 1 Neal 2014-10-03 09:53:45 UTC
Actually, after posting this I realized the only conversion that handled it correctly was of DateTimeKind Utc. Local and Unspecified converted it incorrectly I believe.
Comment 2 Sebastien Pouliot 2014-10-03 13:26:14 UTC
Yeah, sadly that would be breaking change for existing applications. Still we'll discuss this in our next weekly call (after evolve) to see how best to deal with this.
Comment 4 Neal 2014-10-03 13:52:09 UTC
Even passing DateTimeKind local I believe is a bad situation too because you get a UTC NSDate back I believe.
Comment 5 Rolf Bjarne Kvinge [MSFT] 2014-10-05 14:23:01 UTC
NSDate does not have the concept of 'unspecified' or unknown time zone, it represents a specific moment in time, and its internal representation is GMT. This is why NSDate.ToString() will always return a GMT date, it doesn't know anything else.

This is fine, DateTimeKind.Local and DateTimeKind.Utc also represent a specific point in time, and the roundtrip to/from NSDate only looses information about the DateTimeKind the DateTime was created with. The actual point in time the NSDate/DateTime represent is not lost. This is not a problem, if you're creating a string from an NSDate you should always specify in which timezone you want it, and you'll get the right string back.

However, as you've found out, the problem arises when using DateTimeKind.Unspecified, in which case the DateTime does *not* represent a specific point in time, and unfortunately a long time ago it was decided (probably unintentionally) that we should just to whatever DateTime.ToUniversalTime does (it assumes it's DateTimeKind.Local). In hindsight we should probably have made it an exception (or an explicit cast), but it's not something we can do anymore (at least for the Classic API) since it will be a breaking change. We'll discuss internally what we can do for the Unified API.
Comment 6 Neal 2014-10-05 17:10:30 UTC
Rolf, I'm not opposed to "breaking changes" and wouldn't avoid fixing something done wrong because of breaking changes.  What's breaking right now is the unexpected conversions of dates.  The problem is that when I pass a date value to a NSDate it IS being changed so what goes in does not match what comes out.

I'm a big user of Developer Express controls.  With their semi-annual release, or even minor changes, they have their release notes organized as:

1) Breaking changes
2) Additions
3) Bug fixes

I think Xamarin should include what seems to be missing which is #1.  For example when Xam Studio 5.4 came out no one was told that SVN was broke.  The same for iCloud which is still broke (ref 23303).

I suggest breaking the NSDate handling because if you cannot accurately translate System.DateTime to NSDate then don't.  Otherwise we would have had seriously messed up sync, CoreData would be corrupt, the list goes on.

Thanks again...it was eye opening especially when I have to prove Xamarin to Objective C/XCode sub-contractors whom I force to use Xamarin.  This gets chocked up to more lack of trust of the Xam tools which I try to prove the opposite.
Comment 7 Miguel de Icaza [MSFT] 2014-10-20 12:40:17 UTC
We decided to proceed like this:

* We will remove the implicit conversion on Unified API
* We will add an explicit conversion on Unified API
* The explicit conversion will throw in cases that can not be represented in the target NSDate.
Comment 8 Sebastien Pouliot 2014-10-21 15:07:46 UTC
Fixed in master / 55250631c1d0452d89b5d896713d1c2a3f6f4398
Unified will have the new (explicit) behavior while classic will remain the same (implicit).

QA: unit tests added/updated