Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SimpleDateFormat behaviour change in Android Marshmallow

I have encountered an issue with date formatting on Android 6.0, Marshmallow. The code throwing the exception noted below is a pure-Java library (built separately) which my application uses for API requests ("the client"). The library is built with Java 1.6 if that is related...anyway, here is the code;

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd E hh:mm aa", Locale.UK);
Date eventDate = dateFormat.parse(StringUtils.substring(record, 0, 23).trim());

...the record has value;

2015-10-23 Fri 10:59 PM BST   3.60 meters

...which after "trimming" is;

2015-10-23 Fri 10:59 PM
yyyy-MM-dd E hh:mm aa

This code has worked since the good-old days of Froyo and is unit-tested. All that aside Marshmallow throws the exception;

10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: SynchroniseTidePosition.doInBackground
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException: java.text.ParseException: Unparseable date: "2015-10-23 Fri 10:59 PM" (at offset 21)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at java.text.DateFormat.parse(DateFormat.java:579)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at com.oceanlife.rover.handler.XTideParser.parseResponse(XTideParser.java:69)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at com.brantapps.oceanlife.task.SynchroniseTidePosition.doInBackground(SynchroniseTidePosition.java:107)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at com.brantapps.oceanlife.task.SynchroniseTidePosition.doInBackground(SynchroniseTidePosition.java:43)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at android.os.AsyncTask$2.call(AsyncTask.java:295)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
10-23 21:01:56.816 4091-4110/com.oceanlife E/ParseException:     at java.lang.Thread.run(Thread.java:818)

Offset "21" is the space after the '9' in 10:59. Can anyone explain this failure?

Update

Switched over to joda-time and it spat out a more informative error message. Here it is;

Invalid format ... is malformed at "PM"

...so, this is about the AM/PM aspect of the string trying to be parsed - back to the docs

like image 718
BrantApps Avatar asked Oct 23 '15 20:10

BrantApps


1 Answers

The UK Locale appears to have had its definitions of "am" and "pm" altered.

In Marshmallow the UK Locale now has "am" represented as "a.m." and "pm" by "p.m."

String record = "2015-10-23 Fri 10:59 p.m. BST   3.60 meters"
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd E hh:mm aa", Locale.UK);

// note the length is 25 now, not 23... 
Date eventDate = dateFormat.parse(StringUtils.substring(record, 0, 25).trim());

I can't offer an explanation why, but the US Locale works with am/pm and the UK with a.m./p.m.

Edit

It appears that as part of the Locale updates in March 2015, the en_gb locale had its am/pm definitions replaced. source diff

like image 75
adelphus Avatar answered Oct 02 '22 14:10

adelphus