I am using JSON.Net to serialize a DTO and I am getting the following exception on the physical device. THis works on all other devices we have tested on, but is failing on the Samsung Galaxy Tab 3lite SM-T110
running version 4.2.2.
I was having this issue but when I upgraded to Xamarin 3.0, it turned into this below:
06-03 21:17:41.687 E/mono-rt (22071): [ERROR] FATAL UNHANDLED EXCEPTION: System.TimeZoneNotFoundException: Exception of type 'System.TimeZoneNotFoundException' was thrown.
06-03 21:17:41.687 E/mono-rt (22071): at System.TimeZoneInfo.get_Local () [0x00000] in <filename unknown>:0
06-03 21:17:41.687 E/mono-rt (22071): at Newtonsoft.Json.Utilities.DateTimeUtils.GetUtcOffset (DateTime d) [0x00000] in <filename unknown>:0
06-03 21:17:41.687 E/mono-rt (22071): at Newtonsoft.Json.Utilities.DateTimeUtils.WriteDateTimeString (System.Char[] chars, Int32 start, DateTime value, Nullable`1 offset, DateTimeKind kind, DateFormatHandling format) [0x00000] in <filename unknown>:0
06-03 21:17:41.687 E/mono-rt (22071): at Newtonsoft.Json.JsonTextWriter.WriteValue (DateTime value) [0x00000] in <filename unknown>:0
06-03 21:17:41.687 E/mono-rt (22071): at Newtonsoft.Json.JsonWriter.WriteValue (Newtonsoft.Json.JsonWriter writer, PrimitiveTypeCode typeCode, System.Object value) [0x00000] in <filename unknown>:0
06-03 21:17:41.687 E/mono-rt (22071): at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializePrimitive (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonPrimitiveContract contract, Newtonsoft.Json.Serialization.
06-03 21:17:41.695 I/mono-stdout(22071): Executing Command: UpdateRegistration
The program 'Mono' has exited with code 0 (0x0).
EDIT This is the DTO that I am trying to serialize. You can see when the constructor gets called, it sets it to DateTime.Now
. Shouldnt this just assume the local timezone?
public class RecordTargetFrequency : BaseCommand, ICommand {
public Guid TargetId { get; private set; }
public Guid? LocationId { get; private set; }
public Guid TherapistId { get; private set; }
public bool? Increase { get; private set; }
public DateTime TimeStamp { get; private set; }
public RecordTargetFrequency(Guid targetId, Guid? locationId, Guid therapistId, bool? increase) {
TimeStamp = DateTime.Now;
TargetId = targetId;
LocationId = locationId;
TherapistId = therapistId;
Increase = increase;
}
public void Validate() {
ValidateGuid(TargetId);
ValidateGuid(TherapistId);
}
}
I am then serializing it with this line:
JsonConvert.SerializeObject(executedCommand);
Yes, TimeZoneInfo.Local
is somewhat broken on Mono. I've seen three different failure modes here:
I don't have a good solution for that, but if you're trying to record a timestamp, it would be a much better idea to use DateTime.UtcNow
anyway. Then you don't need to worry about time zones at all. In most cases, you should be storing and handling date/time values just in terms of an instant in time, without caring about the time zone or even which calendar is involved.
If you can get a time zone ID from Java.Util.TimeZone.Default
as it looks like you can - you'd want America/New_York
here - then another alternative is to use my Noda Time project, which includes the IANA database. So you could create a ZonedDateTime
which represents exactly what you need. We support Json.NET serialization too, so that part shouldn't be a problem.
Again though, I would encourage you to just use UTC unless you really need the local time.
A couple more options - you might want to consider using DateTimeOffset
instead of DateTime
; if you're just trying to serialize the value as "a date and time with a UTC offset" then DateTimeOffset.Now
might do exactly what you want.
(If none of this helps, please give more context as to what you need and what you expect the JSON to look like.)
Check you time setting for the device. This usually happens when you device time has a wrong time set. Even the time is correct, check if the Time zone is the correct one (eg. for me it's GMT -3 = Greenwich time -3 hours)
A good test is to set it by your self. Sometimes the carrier doesn't give you the correct timezone.
This setting is in System > Date & Time setting.
Ultimately, the problem comes down to the internal use of TimeZoneInfo.Local
on non-Windows devices, but you can avoid this.
If you follow through the source code of DateTimeUtils.WriteDateTimeString
, you'll find that you need to do two things:
Switch to DateFormatHandling.IsoDateFormat
. This should be the default anyway, and is the recommended best practice.
Switch to DateTime.UtcNow
. It usually doesn't make sense to send local times to the server anyway. If for some reason you do, then try serializing a DateTimeOffset
instead, and use DateTimeOffset.Now
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With