Why DateTimeZone.getDefault() does not get updated

2019-05-08 22:54发布

I reviewed many questions related to TimeZones on Stackoverflow, but I could not find the one to the problem I am struggling with:

  • Why doesn't Joda's DateTimeZone.getDefault() return updated timezone on TZ change (after resuming an application?). TimeZone.getDefault() seems to be working just fine.
  • Should I use DateTimeZone.forTimeZone(TimeZone.getDefault()) to get up to date Joda's DateTimeZone object?

Here is how to replicate:

  1. Start app that prints both DateTimeZone.getDefault() and TimeZone.getDefault():

09-15 16:46:59.512 14961-14961/com.example.android.whatever D/TimeZone: DateTimeZone.getDefault()=Europe/London; TimeZone.getDefault()=libcore.util.ZoneInfo[id="Europe/London",...]

  1. Go to settings -> change Timezone to PDT.
  2. Go back to Application that prints stuff (e.g. in onResume()):

09-15 08:49:24.727 14961-14961/com.example.android.whatever D/TimeZone: DateTimeZone.getDefault()=Europe/London; TimeZone.getDefault()libcore.util.ZoneInfo[id="America/Los_Angeles",...]

  1. At this stage I can be rotating the App. The DateTimeZone.getDefault() will be stuck.
  2. Only after application onRestart - the value will be correct.

Why is it so?

2条回答
不美不萌又怎样
2楼-- · 2019-05-08 23:18

Joda-Time caches the default timezone.

If you run this code (in my JVM, the default timezone is America/Sao_Paulo):

System.out.println("JVM default=" + TimeZone.getDefault().getID()); // America/Sao_Paulo
DateTimeZone t1 = DateTimeZone.getDefault();
System.out.println("Joda Default=" + t1); // America/Sao_Paulo

// setting the default timezone to London
TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
System.out.println("JVM default=" + TimeZone.getDefault().getID()); // Europe/London
DateTimeZone t2 = DateTimeZone.getDefault();
System.out.println("Joda Default=" + t2); // America/Sao_Paulo
System.out.println(t1 == t2);  // true

The output will be:

JVM default=America/Sao_Paulo
Joda Default=America/Sao_Paulo
JVM default=Europe/London
Joda Default=America/Sao_Paulo
true

Also note that t1 == t2 returns true, which means they are exactly the same instance.

To set Joda's default timezone after changing the JVM default, you must set it in DateTimeZone too:

// change Joda's default timezone to be the same as the JVM's
DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault()));
DateTimeZone t3 = DateTimeZone.getDefault();
System.out.println("Joda Default=" + t3); // Europe/London
System.out.println(t1 == t3); // false

This outputs:

Joda Default=Europe/London
false

After restarting everything, the cache disappears and Joda-Time gets the new default when first called.

查看更多
狗以群分
3楼-- · 2019-05-08 23:35

You should not directly use Joda-Time but better use the library of Daniel Lew (JodaTimeAndroid - a thin wrapper around Joda-Time) because

  • it has better performance characteristics when loading the tz data on Android
  • it has a suitable broadcast-receiver to track changes of the system timezone.
查看更多
登录 后发表回答