DateTypeAdapter deserialization fails based on user's 24 hour preference
See original GitHub issueI’ve encountered a bug affecting (de)serialization of dates on Android devices using gson 2.7.
Description/Stacktrace
When trying to deserialize this date (Sep 26, 2016 18:13:24
), after switching my device time preferences from 24 hour to 12 hour, using DateTypeAdapter.deserializeToDate
, the following exception was thrown:
java.lang.NumberFormatException: Invalid number: Sep
at com.google.gson.internal.bind.util.ISO8601Utils.parseInt(ISO8601Utils.java:311)
at com.google.gson.internal.bind.util.ISO8601Utils.parse(ISO8601Utils.java:129)
Steps to reproduce
Reproduced on a Nexus 5X running Android 7.0. I have also seen this crash reported from varying devices and Android versions.
- Create a
java.util.Date
object at the following time:Sep 26, 2016 18:13:24
(any date should work, but I will use this date for the example). - Serialize the date object using
DateTypeAdapter.write
, observe that the output is either the string above orSep 26, 2016 6:13:24 PM
depending on your device’s 24 hour time settings. - Go to device date & time settings.
- Switch to using 24-hour format (or vice versa)
- Try to deserialize the date string using
DateTypeAdapter.deserializeToDate
and observe the exception above being thrown.
If you are using the 24-hour format
DateTypeAdapter.deserializeToDate
->Sep 26, 2016 18:13:24
-> works as expectedDateTypeAdapter.deserializeToDate
->Sep 26, 2016 6:13:24 PM
-> throws an exception
If you are using the 12-hour format
DateTypeAdapter.deserializeToDate
->Sep 26, 2016 18:13:24
-> throws an exceptionDateTypeAdapter.deserializeToDate
->Sep 26, 2016 6:13:24 PM
-> works as expected
That the ISO8601Utils cannot deserialize this string does not seem to be the issue. The problem seems to be that the DateFormat
object enUsFormat
is used by default to serialize the Date object. Then when it deserializes it, it tries to format it using this same DateFormat, if that fails it’s falling back to another DateFormat and finally the ISO8601Utils, which also will fail because it’s not meant to handle this format. When the 24-hour time preference is switched, the DateFormat object no longer can correctly format the serialized string, and therefore the adapter falls back to ISO8601Utils which throws an error. DefaultDateTypeAdapter
also appears to have the same problem as DateTypeAdapter
as it is contains the same (de)serialization logic for java.util.Date
objects.
A workaround I am using is to create a TypeAdapter to handle dates and to use ISO8601Utils directly rather than default to using DateFormat so that the serialized string will be agnostic of the user’s time preferences.
Issue Analytics
- State:
- Created 7 years ago
- Comments:16 (1 by maintainers)
Top GitHub Comments
2021 and there is still no fix, this is ridiculous…
One more thing, I’ve needed to add Locale.US inside try 24 hour format, like this:
Otherwise it seems that for some users it still won’t work (I guess depending on their locale)