Tuesday, January 17, 2012

Hawaii Android Automatic Time Zone Bug

This post describes the automatic timezone setting bug that affects Hawaii and many other locations around the globe.  Included below are temporary and permanent workarounds to avoid this issue for existing phones in Hawaii.  I also discuss the proposed location-aware automatic timezone selector that has the greatest chance of fixing this for good for all timezones.

Update Dec 20th, 2012: In the comments below, someone claims this bug has returned in Android 4.2.1.  Can anyone confirm or deny this?  Testing is needed for Android 4.2.1 phones with automatic timezone setting from the cell towers.

Many Android phones in Hawaii are affected by an issue that sets the timezone incorrectly.  Hawaii is always UTC-10, or "ten hours west of UTC", often referred to HST (Hawaiian Standard Time) or Pacific/Honolulu in Android.  Unfortunately, many Android phones incorrectly set themselves to America/Adak which is UTC-10 (HAST) during the winter months.  March - November, this timezone becomes UTC-9 as daylight savings time changes.  Hawaii does not observe DST.

The cell tower tells the phone the current time and offset, always -10 hours in Hawaii in the NITZ string.  Many users do not notice any problems because their phone's visible time is technically correct.  The main app that is visibly affected is the Calendar, especially if you sync your appointments to your GMail account.  Every time you create appointments in your Calendar app, they are stored with the America/Adak timezone instead of Pacific/Honolulu.  Appointments crossing the DST border can then exhibit strange behaviors like appearing to shift an hour.

March 2011 I personally experienced great frustration as appointments on my Google Calendar became messed up when DST changed.  Individual appointments I entered via my Android 2.1 phone shifted one hour early.  Appointments I entered on the Google Calendar web interface did not shift.  It was a mess to sort through and fix many months of appointments.

Is Your Phone Affected?
Most Android phones in Hawaii are affected by this issue.  You can test if your phone is affected by following this procedure:
  1. Make sure Settings > Date & Time > Automatic is enabled then reboot your phone to ensure the test results will be accurate.
  2. Install the Dalvik Explorer app from the Market and run it.
  3. Choose Time Zones from the bottom of the menu.
  4. If it displays America/Adak (default) then your phone is affected.  If it displays Pacific/Honolulu then you are OK.
  5. E-mail your results to wtogami@gmail.com.  Please include your carrier (Sprint, Verizon, T-Mobile, AT&T, etc.) and version of Android you are running.  You can find this somewhere in Settings > About Phone.
  • It appears that most HTC phones are unaffected by this bug.  They seem to have hardcoded a fix somewhere in their framework.  This was confirmed by copying zoneinfo files from a "broken" phone to the HTC phone and the latter didn't break.
  • In rare instances a buggy phone successfully chooses the correct Pacific/Honolulu, however incorrectly saying it observes DST.  An examination of the Android framework source code suggests timing issues that will sometimes allow automatic timezone setting to sort of work.
Temporary Workaround - Manually Set Timezone
In Android 2.3.x, if you turn off Settings > Date & Time > Automatic then manually choose the Hawaii GMT-10:00 timezone, it correctly sets the timezone to Pacific/Honolulu.  It has a bug where it incorrectly displays Hawaiian-Aleutian Standard Time in the menu, but it is actually fixed.  I am unable to confirm if this workaround works in Android 2.1 or 2.2.

This workaround is undesirable as your clock can drift, meaning you need to manually fix your clock periodically.  Also if your phone reboots, you need to manually reset your time as the phone is incapable of keeping the internal clock through reboots.

Android 3.x Honeycomb added an option to independently choose manual timezone selection while allowing Automatic time setting.  Using that option in Android 4.0 Ice Cream Sandwich phones makes this workaround far less problematic as your phone always knows the correct time.

After you have made this change, confirm that your phone's timezone is correct by using Dalvik Explorer.

Permanent Workaround (Requires Root)
If you have rooted your phone (beyond the scope of this post), you may drop-in replace your /system/usr/share/zoneinfo/zoneinfo.* files.  This will fix the problem and allow you to use Automatic time at least until you flash upgrade your ROM.  These replacement zoneinfo.* files should work with any rooted Android phone.

[Hawaii zoneinfo] md5sum ca78cb6eb9889f81ce642ebd0f55afb6

This works by simply deleting America/Adak then rebuilding Android's zoneinfo files with ZoneCompactor.java.  Below I describe why this works.

NITZ Alone is Insufficient
A quick Google search indicates similar problems affecting other parts of the world including Arizona and Sweden.  It is often impossible to correctly guess the desired timezone based upon the NITZ string alone.  My NITZ string here in Hawaii looks like this:
  • The time is in UTC.  The offset is in increments of 15 minutes, so in my case -40 * 15 minutes = -600 minutes = -10 hours.
  • In Hawaii the DST portion of NITZ is always 00.  On the U.S. Mainland this is currently 00 during the winter, but it changes to 01 in March 2012 when DST changes.
  • DST of 00 denotes "daylight savings time is not active at this very moment".  This is a highly unfortunate design flaw of NITZ, as it would be far more useful to know if the local timezone observes DST in general, not if DST is active right now.  Without this distinction, it is impossible to correctly guess which timezone of UTC-10 (Pacific/Honolulu or America/Adak) is correct during the winter months.
Android 4.0.3+ Fixed
One phone running 4.0.1 exhibited the wrong Hawaii timezone.  Various CM9 Android 4.0.3 phones had no problem, and Nexus S 4G with the leaked Google-made Android 4.0.4 also was unaffected.  It looks like the bug was fixed in 4.0.3 by just changing the order.  The general issue is likely still a problem for other overlapping DST-status timezones.
    Android 2.3.7 Code Analysis
    • In CdmaServiceStateTracker, the first time setTimeFromNITZString() runs it does not yet know about the isoCountryCode as it did not yet receive it from the MCC.  So it falls back to getNitzTimeZone which calls findTimeZone() which calls TimeZone.getAvailableIDs() which returns ZoneInfoDB.ids, which was imported and sorted alphabetically ensuring that America/Adak is always before Pacific/Honolulu.  Since it cannot determine any difference between the two from the NITZ string, it chooses the first.
    • The next time setTimefromNITZString() is run it has the iso code it received asynchronously from the MCC, so it instead falls into TimeUtils.getTimeZone().  Here it runs into trouble in this first loop:
    // If the current time zone is from the right country
    // and meets the other known properties, keep it
    // instead of changing to another one.

    if (maybe.equals(currentName)) {
      if (currentOffset == offset && currentDst == dst) {
        return current;
    • It is ensured to return only the previous America/Adak because of the earlier TimeZone current = TimeZone.getDefault(); which looks at the incorrect timezone environment set earlier by CdmaServiceStateTracker.  The first timezone that matches is America/Adak.
    • NOTE: Random timing sometimes allows the MCC and iso country to be known before the first setTimeFromNITZString() call.  This then falls through TimeUtils.getTimeZone() but bypasses this broken conditional to the following conditional where it has a chance to set the timezone differently.  Sometimes you will see in Dalvik Explorer Pacific/Honolulu (default) GMT-10:00 / DST +60 minutes.  This is still incorrect.
    • The above Permanent Workaround that replaces /system/usr/share/zoneinfo/zoneinfo.* files works because it deletes Adak, allowing Honolulu to match first.
    Hard-Coded Framework Fix for Hawaii
    As established above, it is often impossible to correctly guess the desired timezone from the NITZ alone.  My testing suggests that HTC hardcoded a fix for Hawaii somewhere in their framework.  They did not simply delete Adak like my zoneinfo replacement workaround.

    [Patch for CM7 Android 2.3.7]

    A hard-coded framework patch something like this is appropriate to fix automatic timezone selection for Hawaii because the only overlapping timezone for UTC-10 is Adak.  With a population of ~5,000 and zero cell phone service according to the coverage maps of Sprint, Verizon, AT&T and T-Mobile, we can feel reasonably confident that this is an appropriate albeit ugly fix.  Yes, this is ugly.  Got any better ideas?

    I also considered deleting Adak from the zoneinfo files.  But this is a less durable fix as the next time someone updates tzdata and zoneinfo they are highly likely to undo that change.

    Unfortunately, this type of fix would be either too messy or impossible for other parts of the globe as there exist valid overlapping timezones indistinguishable from NITZ strings.  A clean and permanent solution to this issue will need to take location into consideration when choosing a timezone.

    Future Fix: Coarse Location-Aware Automatic Time Zone
    tzdata zone.tab contains latitude and longitude coordinates for each timezone.

    US      +515248-1763929 America/Adak    Aleutian Islands
    US      +211825-1575130 Pacific/Honolulu        Hawaii

    Implementation Plan
    • Modify the Android framework to use the coarse location to aid in selection of the nearest (hopefully correct) timezone in cases where NITZ is ambiguous or does not provide the timezone.
    • This will likely require the user to enable Settings > Location & security to allow even the framework to know its location from GPS, cell towers or nearby wifi.
    • In cases where two ambiguous timezones are near each other, we may be able to refine it by encoding coordinates of the timezone borders.  In the case of Hawaii and Adak this wouldn't be necessary as they are nowhere near each other.  But this may be helpful in cases like Queensland and New South Wales in Australia where two adjacent zones differ only in DST observance.


    1. wow...great report...problem should be fixed...time-keeping is to me the second most basic requirement of cell phones...first being making calls...heh heh...

    2. Thanks for this information. I hope they get an update out to fix this... I'm a non-technical user and am very nervous about rooting my phone to fix it on my own. I am still experiencing this problem in the Hawaiian time zone with an LG G2x and Android 2.3.3

    3. Thanks for the excellent write up. I live in Hawaii, have a Google Nexus running 4.2.1 and unfortunately when calendaring new items it still defaults to Hawaii-Aleution Standard time. I wish this would be fixed. Surprisingly, the only option while selecting a manual Time Zone is "Hawaii", but that option chooses "Hawaii-Aleution" time. I love Android but this is problem seems to be getting worse. At least for those in Hawaii.

    4. This comment has been removed by the author.

    5. Hi Warren, I have a related problem. I live in Barbados (GMT-4), my Carrier is Digicel who use Jamaica MCC 338 throughout their network. Even though the NITZ string has offset -16 (GMT-4) my Samsung S4 (Android 4.3) will always pick Jamaica TZ. Does Android handle NITZ differently for single Time Zone countries versus multi time zone countries? Maybe Goog is not aware that Digicel spans multiple time zones.

      06-30 09:15:10.491 3346 3437 D RILJ : [rild] [UNSL]< UNSOL_NITZ_TIME_RECEIVED 14/06/30,14:15:09-16,00,America!Jamaica,338

    6. My DROID Turbo on 4.4.4 and my wife's LG Enact on 4.2.1 Verizon both changed time automatically this morning. Time zone said "Hawaii - Aleutian Daylight Time" and I had to change it manually by turning off Auto time zone and setting it to HST.