The date format "MMM" on a Samsung Android 13 device works well for all months except September.
val df = SimpleDateFormat("MMM dd, yyyy")
// meet the Java API but throw an exception on SM Android 13
val date1: String = df.format(df.parse("Sep 11, 2001"))
// works on SM Android 13
val date2: String = df.format(df.parse("Sept 11, 2001"))
Here is the month format in a DatePicker control in SM-X700. All months are in "MMM" but September is "Sept".
I only see this issue on Samsung Android 13. The Samsung Android 12 and Google Nexus Android 13 use "Sep" correctly. Is it an Samsung Android 13 bug?
Related
Following is the code to parse date. I have used 'joda-time:joda-time:2.9.9' lib for formatter.
String date = "Sun Sep 04 17:29:52 +0000 2022";
DateTimeFormatter dateFormat = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss Z
yyyy").withLocale(Locale.UK);
dateFormat.parseDateTime(date);
Above code was throwing illegelArgument exception in Android 12. When I changed locale from UK to US, its started working.
But strange thing is that if I tried to parse Wed Mar 23 14:28:32 +0000 2016 this date with above code, its working in all OS.
Out of mind question is why one date is getting parse and another is not.
What's actually changed in Android 12 that suddenly code is getting failed?
What's actually changed in Android 12 that suddenly code is getting
failed?
Earlier, the short name for September in the Locale.UK was Sep but it got changed to Sept starting with Java 16. Check this related thread.
There is no change in other short names in the Locale.UK and therefore it worked for Wed Mar 23 14:28:32 +0000 2016 for example.
Modern Date-Time API
For the sake of completeness, I would like to discuss a bit about the modern date-time API. Probably you must have already seen the following note on the Home Page of the Joda-Time API:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this
project.
Demo using the modern date-time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "Sun Sep 04 17:29:52 +0000 2022";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss Z yyyy", Locale.ROOT);
OffsetDateTime zdt = OffsetDateTime.parse(strDateTime, formatter);
System.out.println(zdt);
}
}
Output:
2022-09-04T17:29:52Z
Notice that I have use Locale.ROOT in the demo. If you use Locale.UK, it will throw the same error that you have got. However, if you change Sep to Sept and use Locale.UK, it will work.
Learn more about the modern Date-Time API from Trail: Date Time.
import java.text.SimpleDateFormat;
import java.util.Locale;
Locale locale = new Locale("bd", "bn");
String pattern = "EEEEE MMMMM yyyy HH:mm:ss.SSSZ";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, locale);
String date = simpleDateFormat.format(System.currentTimeMillis());
System.out.println("DateTime :: " + date);
Greetings of the day.
In my application, I have displayed list of months statically currently.
But, I want list of months dynamically. i.e. 12 months which are lesser or equal to current running month of current year.
For Example today is 2nd May 2020, So, List should be as below :
Jun, 2019. Jul, 2019. Aug, 2019. Sep, 2019. Oct, 2019. Nov, 2019. Dec,
2019. Jan, 2020. Feb, 2020. Mar, 2020. Apr, 2020. May, 2020.
Please guide how can I achieve this thing in Android.
Thanks.
val formatter = SimpleDateFormat("MMM, yyyy")
val list = arrayListOf<String>()
Calendar.getInstance().let {
calendar ->
calendar.add(Calendar.MONTH, -11)
for (i in 0 until 12) {
list.add(formatter.format(calendar.timeInMillis))
calendar.add(Calendar.MONTH, 1)
}
}
print(list)
java.time and ThreeTenABP
final int monthsInYear = 12;
YearMonth currentMonth = YearMonth.now(ZoneId.of("Pacific/Kosrae"));
YearMonth sameMonthLastYear = currentMonth.minusYears(1);
List<YearMonth> months = new ArrayList<>(monthsInYear);
for (int i = 1; i <= monthsInYear; i++) {
months.add(sameMonthLastYear.plusMonths(i));
}
System.out.println(months);
Output:
[2019-06, 2019-07, 2019-08, 2019-09, 2019-10, 2019-11, 2019-12, 2020-01, 2020-02, 2020-03, 2020-04, 2020-05]
I recommend you keep YearMonth objects in your list. For formatted output use a DateTimeFormatter:
DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("MMM, uuuu", Locale.ENGLISH);
for (YearMonth ym : months) {
System.out.println(ym.format(monthFormatter));
}
Jun, 2019
Jul, 2019
Aug, 2019
... (cut) ...
Apr, 2020
May, 2020
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Artifact used (androidx.textclassifier:textclassifier:1.0.0-alpha02):
Version used:1.0.0-alpha02
I am working on an app which is based on TextClassifier. In order to support back-port on API 14 - 27, I use the AndroidX's TextClassifier, however, what disappointed me is that the predicting results of the NONE-P devices (API 14-27) are different from API 28 which is Android P. I figure out that internal of AndroidX is using the ">=P" for different solution which means, on 28, the library uses native ML solution (maybe).
i.e:
to predict the date-time text which is selected or passed into the app.
On Android P:
July 20, 1969, at 20:17 -> inference: date or DateTime and the score: 0.9897
<= O:
July 20, 1969, at 20:17 -> inference: other and the score: 0.9897
Is there any idea to let AndroidX's TextClassifier more AI-strong, like native Android P?
Issue
I just installed the upgrade version Lollipop on my android phone and this doesn't work anymore:
String time = "Apr 07 10:35:27 CEST 2015";
long l1 = new SimpleDateFormat("MMM dd HH:mm:ss zzz yyyy").parse(time).getTime();
long l2 = new SimpleDateFormat("MMM dd HH:mm:ss zzz yyyy",
Locale.ENGLISH).parse(time).getTime();
Both doesn't work:
W/System.err(11473): java.text.ParseException: Unparseable date: "avr. 07 10:35:27 CEST 2015" (at offset 17)
The problem is that SimpleDateFormat now returns GMT+02:00 instead of previously CEST after I installed 5.0
"CEST" is not a recognized timezone pattern according to CLDR, which Android uses. It may be that it was recognized in prior because SimpleDateFormat was lifted from Apache Harmony, which followed Java's own time format standard.
SimpleDateFormat parse works in a JUnit test (Robolectric test runner), but fails if run on device.
#Test
public void testDateParse() throws ParseException {
String datetime = "Wed Sep 03 12:59:27 BST 2014";
new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH)
.parse(datetime);
}
When it fails on the device the exception says:
java.text.ParseException: Unparseable date: "Wed Sep 03 12:59:27 BST 2014" (at offset 20)
Offset 20 is the B of BST, so it's timezone related.
Indeed "GMT" works: String datetime = "Wed Sep 03 12:59:27 GMT 2014";
I guess the interesting question here is why does this run ok on Robolectric but fails to run on an Android test.
Robo runs on the JVM and there is a difference in behaviour for Timezone parsing between Android and good ol' Java.
In the Android documentation:
Other than the special cases "UTC" and "GMT" (which are synonymous in this context, both corresponding to UTC), Android does not support the deprecated three-letter time zone IDs used in Java 1.1.
In the Java documentation:
the ID for a TimeZone, either an abbreviation such as "PST", a full name such as "America/Los_Angeles", or a custom ID such as "GMT-8:00". Note that the support of abbreviations is for JDK 1.1.x compatibility only and full names should be used.
So the answer is that the 3-letter abbreviations should not be used (because they are ambiguous), but can be used on the JVM for compatibility reasons, but not on Android.