Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
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
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.
Created attachment 8297 [details]
NSDate from DateTime example app
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.
NC Software, Inc.
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.
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.
Even passing DateTimeKind local I believe is a bad situation too because you get a UTC NSDate back I believe.
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.
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
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.
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.
Fixed in master / 55250631c1d0452d89b5d896713d1c2a3f6f4398
Unified will have the new (explicit) behavior while classic will remain the same (implicit).
QA: unit tests added/updated