This is Xamarin's bug tracking system. For product support, please use the support links listed in your Xamarin Account.
Bug 4902 - Determine TimeZone from java.util.TimeZone, not persist.sys.timezone
: Determine TimeZone from java.util.TimeZone, not persist.sys.timezone
Status: RESOLVED FIXED
Product: Android
Classification: Xamarin
Component: Class Libraries
: 4.1.x
: PC Windows
: High critical
: ---
Assigned To: Marek Habersack
:
:
:
:
  Show dependency treegraph
 
Reported: 2012-05-05 11:45 EDT by Stuart Lodge
Modified: 2014-04-16 11:00 EDT (History)
18 users (show)

See Also:
Tags:
Test Case URL:
External Submit: ---


Attachments

Description Stuart Lodge 2012-05-05 11:45:50 EDT
Hi

I'm sometimes seeing an exception with details:

System.ArgumentNullException: Argument cannot be null.
Parameter name: path2

>	0x21 in System.IO.Path.Combine at /home/jon/Development/xamarin/mono/mcs/class/corlib/System.IO/Path.cs:103	C#
     0x6 in System.TimeZoneInfo+ZoneInfoDB.GetTimeZoneData at
/home/jon/Development/xamarin/mono/mcs/class/System.Core/System/TimeZoneInfo.Android.cs:179
   C#
     0x5 in System.TimeZoneInfo+ZoneInfoDB._GetTimeZone at
/home/jon/Development/xamarin/mono/mcs/class/System.Core/System/TimeZoneInfo.Android.cs:168
   C#
     0x69 in System.TimeZoneInfo+ZoneInfoDB.GetTimeZone at
/home/jon/Development/xamarin/mono/mcs/class/System.Core/System/TimeZoneInfo.Android.cs:213
   C#
     0x2A in System.TimeZoneInfo+ZoneInfoDB.get_Default at
/home/jon/Development/xamarin/mono/mcs/class/System.Core/System/TimeZoneInfo.Android.cs:274
   C#
     0xA in System.TimeZoneInfo.get_Local at
/home/jon/Development/xamarin/mono/mcs/class/System.Core/System/TimeZoneInfo.cs:88
   C#
     0x0 in Newtonsoft.Json.Utilities.DateTimeUtils.GetUtcOffset    C#
     0x3 in Newtonsoft.Json.JsonConvert.WriteDateTimeString    C#

This is when using the PCL version of JSON.Net

Looking at the call stack I guess this is a monodroid issue?

I haven't got a simple reproduction of this but it's happening frequently in
the 
 samples on the vNext mvx branch:
https://github.com/slodge/MvvmCross/tree/vnext

Stuart
Comment 1 Jonathan Pryor 2012-05-24 15:27:43 EDT
Is this inside the debugger? Is this a first-chance exception?

I ask because TimeZoneInfo.Android.cs:213 is in the stack trace, which is
clearly in a try/catch block:

https://github.com/mono/mono/blob/master/mcs/class/System.Core/System/TimeZoneInfo.Android.cs#L212

This shouldn't be "escaping" to calling code, unless things are going "weird"
(which usually occurs when running .apk's which haven't been zipaligned; are
you custom signing this app?)

Unrelated, TimeZoneInfo.Android.cs:179 is a Path.Combine call, so the only
reason we'd get an ArgumentNullException is if `name` were null, which implies
that GetDefaultTimeZoneName() is returning null:

https://github.com/mono/mono/blob/master/mcs/class/System.Core/System/TimeZoneInfo.Android.cs#L286

Does your device have the persist.sys.timezone system property set? i.e. what's
the output of this command?

    adb shell getprop persist.sys.timezone

It should be a non-empty string, e.g.

    America/New_York
Comment 2 Stuart Lodge 2012-05-25 12:46:01 EDT
I can't repro the problem right now - will need to remember the exact problem
and remove the workaround.

The problem was a full exception though - it wasn't being handled.

I have seen some odd effects when debugging PLPs - they just don't seem to be
"entirely normal" when it comes to stepping in and out of code - but this could
be down to me and might be a red herring here.



I can tell you that my Galaxy Note is giving me an empty timezone for that adb
call:

"
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell getprop
pers
ist.sys.timezone


C:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell getprop
pers
ist.sys.timezone


C:\Program Files (x86)\Android\android-sdk\platform-tools>
"

I tried it twice just to be sure!
Comment 3 Stuart Lodge 2012-05-25 12:46:24 EDT
placing it back to NEW to see if that adb shell info helps
Comment 4 Jonathan Pryor 2012-06-04 14:45:58 EDT
Very, very strange; AOSP uses the persist.sys.timezone system property:

https://github.com/android/platform_dalvik/blob/0c9612f9d7ff9fc0a61cc9eeb37acaabb7b28700/libcore/luni/src/main/java/java/util/TimeZone.java#L203
https://github.com/android/platform_dalvik/blob/0c9612f9d7ff9fc0a61cc9eeb37acaabb7b28700/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/ZoneInfoDB.java#L310
https://github.com/android/platform_dalvik/blob/0c9612f9d7ff9fc0a61cc9eeb37acaabb7b28700/libcore/luni/src/main/java/org/apache/harmony/luni/internal/util/TimezoneGetter.java#L54
https://github.com/android/platform_frameworks_base/blob/master/core/java/com/android/internal/os/RuntimeInit.java#L104

(TimeZone.getDefault() calls ZoneInfoDB.getDefault() calls
TimezoneGetter.getInstance() which is set to an inner class in RuntimeInit
which grabs the persist.sys.timezone system property.)

Of course, all of that is subject to change (internal!), but my Galaxy Nexus
(Android v4.0.4) still has the persist.sys.timezone system property, so I don't
think it's changed that much. :-/

Fortunately, I think I've found an in-Java way to get an appropriate TimeZone
string: Java.Util.TimeZone.Default.ID

Can you run a MfA app on your Galaxy Note and print out the value of the
Java.Util.TimeZone.Default.ID property? Is it also the empty string or is it
something reasonable?

Thanks
 - Jon
Comment 6 Stuart Lodge 2012-06-06 02:32:01 EDT
Thanks Jon

The value of ID is "GMT"

Stuart


-        Default   
{java.util.SimpleTimeZone[id=GMT,offset=0,dstSavings=3600000,useDaylight=false,startYear=0,startMode=0,startMonth=0,startDay=0,startDayOfWeek=0,startTime=0,endMode=0,endMonth=0,endDay=0,endDayOfWeek=0,endTime=0]}
   Java.Util.SimpleTimeZone
-        base    {Java.Util.TimeZone}    Java.Util.TimeZone
-        base    {Java.Lang.Object}    Java.Lang.Object
+        Class    {Java.Lang.Class}    Java.Lang.Class
        Handle    0x40513ba8    System.IntPtr
+        Static members        
+        Non-public members        
        DisplayName    "GMT+00:00"    string
        DSTSavings    0    int
        ID    "GMT"    string
+        Static members        
-        Non-public members        
        ThresholdClass    0x400985a0    System.IntPtr
+        ThresholdType    {System.MonoType}    System.MonoType
        RawOffset    0    int
+        Static members        
+        Non-public members
Comment 7 Atsushi Eno 2012-09-11 11:54:03 EDT
Does it still matter? Since bug #6468 is fixed now and thus Path part should be
also working too.
Comment 8 Jonathan Pryor 2012-09-11 12:22:51 EDT
@Eno: Yes, this still matters; this is a different issue.

The problem here is that some devices lack the persist.sys.timezone system
property (Comment #2), which TimeZoneInfo uses to determine the default
timezone:

https://github.com/mono/mono/blob/master/mcs/class/System.Core/System/TimeZoneInfo.Android.cs#L289

(Hopefully that link is correct; I cannot currently verify as github is down).

Since some devices don't have the persist.sys.timezome system property, it
cannot be relied upon.

The solution is to have a "cross call" from System.Core.dll into
Mono.Android.dll; see e.g. mcs/class/System/AndroidPlatform.cs. This "cross
call" would invoke a method within Mono.Android.dll which would return the
value of Java.Util.TimeZone.Default.ID, thus allowing the default timezone to
be looked up even on platforms that don't provide persist.sys.timezone.
(Furthermore, this "cross-call" should be used INSTEAD OF the current system
property lookup code.)
Comment 9 Stuart Lodge 2013-01-03 11:21:35 EST
I think I might have just stumbled upon this issue again - or maybe its
something similar to it?

Basically, I'm trying to use JSON.Net in MonoDroid to save an object.

This object includes a time which has been created using System.DateTime.UtcNow

When I run it, it hits a NullReferenceException in:

        StackTrace    "  at
Newtonsoft.Json.Utilities.DateTimeUtils.GetUtcOffset (DateTime d) [0x00000] in
<filename unknow…"    string

Looking at the code -
https://github.com/ayoung/Newtonsoft.Json/blob/master/Newtonsoft.Json/Utilities/DateTimeUtils.cs

It seems this is most likely caused by:

    utcOffset = TimeZoneInfo.Local.GetUtcOffset(d); 

so TimeZoneInfo.Local is null

Testing this in a simple app, confirms this.

Totally understand that this might be 'something special' about my Galaxy Note
- but thought I'd report it anyway - as I think TimeZoneInfo.Local should never
be null?
Comment 10 Stuart Lodge 2013-01-17 10:01:01 EST
I'm seeing this crash a lot at present.

Is there any fix planned for this?

If not, can we move this bug to REJECTED? POSTPONED? etc

I'm finding it a bit embarrassing explaining to my customer that this bug is
still NEW where it was reported 8 months ago.

Thanks

Stuart
Comment 11 Stuart Lodge 2013-01-17 10:08:51 EST
Or maybe I've confused things... and this is actually >1 bug?
Comment 12 NiWa 2013-05-30 02:52:34 EDT
What about this Bug? As far as I know there is no solution or fix for this
problem.

Thanks
Nico
Comment 13 Atsushi Eno 2013-06-28 03:27:15 EDT
I adb shell getprop persist.sys.timezone and "Console.WriteLine
(Java.Util.TimeZone.Default.ID);" on my Galaxy Note, and both returned
Asia/Tokyo (as expected).

I wonder if UK (GMT) is handled specially somewhere (either in Android, mono,
or XA).
Comment 14 NiWa 2013-06-28 03:38:04 EDT
@Eno: I really think this has something to do with the device used. On my
Galaxy SII (GT-I9100) with Android 4.0.4 it does not work no matter what
timezone (de-DE or somthing else) is set.
Comment 15 NiWa 2013-06-28 03:46:59 EDT
Java.Util.TimeZone.Default.ID returns "GMT" only.
Comment 16 NiWa 2013-07-01 03:08:08 EDT
Please forget the mention of locale de-DE, because it *obviously* has nothing
to do with the current issue.

BUT, after further testing I was able to observe the correct behavior of the
JSON serializer, after I turned off the automatic timezone update and manually
set the timezone to GMT+1.

After that 'getprop persist.sys.timezone' returns the expected value and the
JSON serializer runs successfully through the serialization of a DateTime
object.
Comment 17 Jonathan Pryor 2013-07-22 15:55:37 EDT
*** Bug 13382 has been marked as a duplicate of this bug. ***
Comment 18 José Pereira 2013-08-21 11:12:34 EDT
I'm having this same issue...
I run the 'adb shell getprop persist.sys.timezone' command and it returns:

Europe/London

Still, when I try to serialize na object that has a DateTime property, it
throwns an exception...

I've tried to set manually the timezone and the result is the same...
I'm testing it on a Sony Experia L with Android 4.1.2

Any news regarding this bug. How can I overcome this behaviour?
Comment 19 Stephen Feest 2013-08-28 13:09:40 EDT
I am having the same issue with Xamarin.Android 4.8.1 on my Nexus 7 running
Android 4.3. Namely when I try to serialize a DateTime value with Json.NET I
get a NullReferenceException in
Newtonsoft.Json.Utilities.DateTimeUtils.GetUtcOffset(DateTime d). Using a very
simple test project I can confirm that the cause of this is TimeZoneInfo.Local
returning null.

On this particular tablet I've tried changing the time zone manually and
disabling 'Automatic date & time' but that doesn't seem to change anything.

adb shell getprop persist.sys.timezone returns the correct time zone
"Europe/London"

In my opinion this is quite a serious bug as there doesn't seem to be any
obvious workaround for those of us whose apps rely on timezone information.
Comment 20 Jonathan Pryor 2013-08-28 14:16:25 EDT
@José Pereira: What's the exception you get when deserializing the DateTime?

This bug (Bug #4902) is about proper behavior when the persist.sys.timezone
isn't set; if it is set, that's a different bug, for which I'll need additional
information.
Comment 22 Stephen Feest 2013-08-28 15:03:45 EDT
Thanks Jonathan. The problem I'm experiencing does indeed look like it's caused
by bug #13686. Sorry for the confusion!
Comment 23 Chuck Pinkert 2013-09-08 22:51:01 EDT
Also having this problem using mvvmcross / json.net in one app and my other app
has it when just trying to reference the current timezone on some devices that
don't set persist.sys.timezone.
Comment 24 vlad.dimitrov 2013-10-06 03:23:33 EDT
Also having the same issue while trying to serialize an object. This is what I
get:

{System.NullReferenceException: Object reference not set to an instance of an
object
  at Newtonsoft.Json.Utilities.DateTimeUtils.GetUtcOffset (DateTime d)
[0x00000] in <filename unknown>:0 
  at Newtonsoft.Json.JsonConvert.WriteDateTimeString (System.IO.TextWriter
writer, DateTime value, DateFormatHandling format) [0x00000] in <filename
unknown>:0 
  at Newtonsoft.Json.JsonTextWriter.WriteValue (DateTime value) [0x00000] in
<filename unknown>:0 
  at Newtonsoft.Json.JsonWriter.WriteValue (System.Object value) [0x00000] in
<filename unknown>:0 
  at
Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializePrimitive
(Newtonsoft.Json.JsonWriter writer, System.Object value,
Newtonsoft.Json.Serialization.JsonPrimitiveContract contract,
Newtonsoft.Json.Serialization.JsonProperty member,
Newtonsoft.Json.Serialization.JsonContainerContract containerContract,
Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in
<filename unknown>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue
(Newtonsoft.Json.JsonWriter writer, System.Object value,
Newtonsoft.Json.Serialization.JsonContract valueContract,
Newtonsoft.Json.Serialization.JsonProperty member,
Newtonsoft.Json.Serialization.JsonContainerContract containerContract,
Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in
<filename unknown>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject
(Newtonsoft.Json.JsonWriter writer, System.Object value,
Newtonsoft.Json.Serialization.JsonObjectContract contract,
Newtonsoft.Json.Serialization.JsonProperty member,
Newtonsoft.Json.Serialization.JsonContainerContract collectionContract,
Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00000] in
<filename unknown>:0 }
    base: {System.SystemException}

I am using Xamarin.Android 4.8.03009 and am running the code on LG P500
Comment 25 vlad.dimitrov 2013-10-06 03:53:24 EDT
Looks like the problem is coming from the fact that TimeZoneInfo.Local == null.

This on this device because the Time zone info was set to automatic and there
was no SIM card inside so it could not determine the time zone.

After setting the time zone manually the code started working.
Comment 26 Dale King 2014-02-17 16:38:05 EST
Any chance this bug will get fixed soon? High, critical bug still open after 1
year and a half?!!?

It is easy to replicate. All I have to do is create a new emulator (GenyMotion
in my case) and don't set a timezone. It is set to automatic and
TimeZoneInfo.Local will be null. If you set a timezone it isn't.
Comment 27 Greg Shackles 2014-03-20 16:05:53 EDT
Are there any plans for getting a fix for this in the roadmap? I'm hitting this
in my apps as well.
Comment 28 Andrew 2014-04-04 11:00:25 EDT
In case of Genymotion, go to Android settings and set your/any timezone. After
that TimeZoneInfo.Local will not be null.
Comment 29 Dale King 2014-04-04 13:12:58 EDT
Yes I know how to work around it in my emulator, the point was it is dead
simple to reproduce, so should not be that much work to fix.
Comment 30 Marek Habersack 2014-04-16 11:00:54 EDT
The bug is fixed in the master branch, in the following commits:

 b7feb685480fcfc33f9b7e21bb5401c9d6b601fb
 3aa8a4821c0edb7c3deb173971d8f8392c844eec
 88d1fc677d6c2ac920c77973f67e4630b61cc800
 cc23090bc07c8ad3663d58cf401153fd2455a07a

The fix implements a fall-back to retrieve the default time zone name from
Java.Util.TimeZone.Default.ID should the 'persist.sys.timezone' system property
be missing.

Note You need to log in before you can comment on or make changes to this bug.