Custom Android date formatting respecting current Locale - android

Is there a way how to specify dateFormat elements and respect current locale rules? I know that I can use SimpleDateFormat and specify the format I like - but it may be wrong in different country.
I tried to mask the elements in DateFormat but it accepts only SHORT, MEDIUM and LONG:
DateFormat dayMonth = DateFormat.getDateInstance(DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD | DateFormat.MONTH_FIELD);
Caused by: java.lang.IllegalArgumentException: Illegal date style: 11
at java.text.DateFormat.checkDateStyle(DateFormat.java:843)
at java.text.DateFormat.getDateInstance(DateFormat.java:378)
I want to get "Oct 2016", or "Říj 2016". This can be implemented with:
DateFormat dayMonth = new SimpleDateFormat("MMM yyyy");
But I do not want to hard code this format in my app. I see one way only: put it into strings.xml and a translator will have to set it up. Or is there better way?

Android has DateFormat.getBestDateTimePattern() to achieve this
pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMyyyy");
dayMonth = new SimpleDateFormat(pattern);
The only downside is the API level of 18. I personally used the result of DateFormat.getMediumDateFormat() as fallback. Alternatively you could just ignore the locale for older devices and use new SimpleDateFormat("MMM yyyy") there as fallback or try to backport this one method.
OP Edit
I tried on Nexus 5x with Android 6 a following code
for (Locale locale : locales) {
format = android.text.format.DateFormat.getBestDateTimePattern(locale, "MMMyyyy");
DateFormat dateFormat = new SimpleDateFormat(format, locale);
log.debug("{}: {}", locale.getCountry(), dateFormat.format(new Date()));
}
And here are some result:
NA: Jul 2016
AE: يوليو ٢٠١٦
BG: 07.2016 г.
CZ: červenec 2016
FR: Goue 2016
DE: Juli 2016
GB: Jul 2016
FI: heinä 2016
IT: Lui 2016
HR: srp 2016.
RU: июль 2016

Related

Chinese New Year Date on Android

How one could get Chinese New Year Date on Android?
Since API level 24 Android has Chinese Calendar class.
https://developer.android.com/reference/android/icu/util/ChineseCalendar
However, doing it like this returns wrong date (Feb 12 for 2023).
val chinese = ChineseCalendar.getInstance()
chinese.set(ChineseCalendar.MONTH, 0)
chinese.set(ChineseCalendar.DAY_OF_MONTH, 1)
I was able to get Gregorian date for Chinese new year in the following way. Getting Chinese calendar is done using simple instantiation ChineseCalendar(). No need to call getInstance().
val chinese = ChineseCalendar()
chinese.set(ChineseCalendar.MONTH, 0)
chinese.set(ChineseCalendar.DAY_OF_MONTH, 1)
println("chinese " + chinese.time.toString())
In the logs I got
chinese Sun Jan 22 13:24:41 GMT+02:00 2023
You can also add year to get next new year date, like this
chinese.add(ChineseCalendar.YEAR, 1)
and get
chinese Sat Feb 10 13:27:41 GMT+02:00 2024

JodaTime will always change to 2015 if withYear set to 2016

This is really driving me crazy. The code below
DateTime dt = new DateTime()
.withYear(2014)
.withWeekOfWeekyear(52)
.withDayOfWeek(1);
DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("d MMM yyyy");
String firstDayOfWeek = dateTimeFormatter.print(dt);
Log.v(FILE_NAME,"display date? " + firstDayOfWeek);
dt = new DateTime()
.withYear(2015)
.withWeekOfWeekyear(52)
.withDayOfWeek(1);
String lastDayOfWeek = dateTimeFormatter.print(dt);
Log.v(FILE_NAME,"display date? " + lastDayOfWeek);
dt = new DateTime()
.withYear(2016)
.withWeekOfWeekyear(52)
.withDayOfWeek(1);
lastDayOfWeek = dateTimeFormatter.print(dt);
Log.v(FILE_NAME,"display date? " + lastDayOfWeek);
Somehow will always output:
display date? 22 Dec 2014
display date? 21 Dec 2015
display date? 21 Dec 2015
As you can see, the last display date should display 2016, not 2015. It seems that everytime I set withYear to 2016, it will magically change to 2015. Is this a bug or am I doing something wrong? I have cleaned and rebuild my project many times but the output is the same.
The method withYear(...) does not do what you think because it uses the standard calendar year and not the year of week date as described in ISO-8601-paper. Please compare following two snippets. Only the second one does what you need:
DateTime dt = new DateTime().withYear(2016).withWeekOfWeekyear(52).withDayOfWeek(1);
System.out.println("joda=" + dt); // joda=2015-12-21T18:26:12.776+01:00
DateTime dt2 =
new DateTime().withWeekyear(2016).withWeekOfWeekyear(52).withDayOfWeek(1);
System.out.println("joda=" + dt2); // joda=2016-12-26T18:27:59.606+01:00
See also the documentation. The fine difference between calendar year and weekbased year is only noticeable at the end or start of a year (like today).
Explained in detail the behaviour:
If choosing new DateTime() for today, the second of January 2017 and then setting the calendar year to 2016 results in: 2016-01-02. But this date is in week-of-year 53 belonging to week-based-year 2015. This 53rd week starts on 2015-12-28, so the expression withWeekOfWeekyear(52) will go back one week to 2015-12-21 (what you observe in first case).

SimpleDateFormat behaves differently on different tablet

I have an Asus Fonepad first generation(android 4.1.2) and an Asus Fonepad second generation(android 4.3).
I use the following code to parse the date to the desired format in my app:
SimpleDateFormat df = new SimpleDateFormat("MMM dd HH:mm:ss yyyy", /*new Locale("nl", "NL")*/Locale.GERMANY);
df.setTimeZone(TimeZone.getTimeZone(/*"Europe/Amsterdam"*/"Europe/Berlin"));
String time = df.format(new Date());
The above code results in "Dez 23 17:09:25 2013" on the first generation fonepad and "Dez. 23 17:09:25 2013" on the second generation fonepad.
As you can see, the second generation adds a dot after the month.
this causes a parsexception on the server side.
Why does SimpleDateFormat behave differently on different devices(android versions)? This is worrying.
Is there a way to always get the same format? What is the solution to this?
Thanks.
SimpleDateFormat (and some other framework classes) use icu4c library to format content. Month format for DE was changed between 49.2 and 50.1 versions of this library.
No, you can't expect same behavior for all android versions.
Link to sources: https://android.googlesource.com/platform/external/icu4c/+/android-4.4.2_r1/data/locales/de.txt
Add: If you sending data to a server than solution is to use only numbers: 12 will be always 12 for December.

Android translating date depending on Locale

I can"t get to work a simple code in a fresh project that is suppose to simply write one date in many langage depending on the Locale set.
Locale[] locales = new Locale[] {
Locale.JAPAN,
Locale.CHINA,
Locale.KOREA,
Locale.TAIWAN,
Locale.ITALY,
Locale.FRANCE,
Locale.GERMAN
};
// Get an instance of current date time
Date today = new Date();
//
// Iterates the entire Locale defined above and create a long
// formatted date using the SimpleDateFormat.getDateInstance()
// with the format, the Locale and the date information.
//
for (Locale locale : locales) {
System.out.println("Date format in "
+ locale.getDisplayName()
+ " = "
+ SimpleDateFormat.getDateInstance(
SimpleDateFormat.LONG, locale)
.format(today).toUpperCase());
}
}
Here is the link of this code : URL of the code below
Now here is what it's suppose to display
Date format in Japanese (Japan) = 2009/01/04
Date format in Chinese (China) = 2009年1月4日
Date format in Korean (South Korea) = 2009년 1월 4일 (일)
Date format in Chinese (Taiwan) = 2009年1月4日
Date format in Italian (Italy) = 4 GENNAIO 2009
Date format in French (France) = 4 JANVIER 2009
Date format in German = 4. JANUAR 2009
And here is MY display :
Date format in Japanese (Japan) = 2012 7 21
Date format in Chinese (China) = 2012 7 21
Date format in Korean (South Korea) = 2012 7 21
Date format in Chinese (Taiwan) = 2012 7 21
Date format in Italian (Italy) = 2012 7 21
Date format in French (France) = 2012 7 21
Date format in German = 2012 7 21
PROBLEM : What's wrong ? Am I forgeting some obvious thing ? Do you have any lead ?
Thanks.
As it turned out it's a device-specific problem. The code works on a phone with correct locale data and also on emulator. On HTC Desire there are some ROMs which have locale data corrupted. More on this issue.

ParseException only on Galaxy Nexus

I tested my app on 5 various phones and this exception occurs only on Samsung Galaxy Nexus:
java.text.ParseException: Unparseable date: "Sun, 19 Feb 2012 14:02:43 +0100" (at offset 0)
My input string:
<pubDate>Sun, 19 Feb 2012 14:02:43 +0100</pubDate>
My code:
private String getString(Element item, String tag) {
Element e = (Element) item.getElementsByTagName(tag).item(0);
return e.getFirstChild().getNodeValue();
}
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ZZZZ");
String tmpDate = getString(item, "pubDate");
Date pubDate = new Date(System.currentTimeMillis());
pubDate = sdf.parse(tmpDate);
Is this a problem of Android 4.0 or I made some mistake?
In addition I have a problem with my national signs. I have xml in UTF-8, and I want to display it in WebView. I have UTF-8 encoded html file and it works perfect on all devices except Galaxy Nexus - it display some strange characters instead of my national signs.
Do you have any ideas?
I would bet that the Nexus has a different locale set by default. Try using the
SimpleDateFormat(String pattern, Locale locale)
variant of the constructor to explicitly set the locale you expect in your date string.

Categories

Resources