Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert an Arabic String date to a java 8 date object?

I'm working on a web monitoring project in Arabic and I want to convert string date like this one:

الاثنين 24 أبريل 2017 - 15:00

to Java 8 date object. How can I do that?

like image 805
Meryem Moumen Avatar asked Apr 26 '17 14:04

Meryem Moumen


3 Answers

The answers of @Ole and @slim are working, but not for the reason they think.

First observation - the nu-extension is unnecessary for given example:

Oles suggestion would also work for the locale new Locale("ar", "SA") instead of Locale.forLanguageTag("ar-SA-u-nu-arab"). So what does the unicode-nu-extension here? Nothing. Next question:

What is the nu-extension supposed to do here?

The nu-code-word "arab" is specified by the unicode consortium to yield arabic-indic digits. But the input to be parsed does only have western digits 0-9 (which are historically overtaken from Arab people and specified as code word "latn" - a misnomer by the way). So if the nu-extension had really done its job here then parsing should have failed because arabic-indic digits are not 0-9 but:

٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩

Obviously, the nu-extension is not supported in general by new time-API in Java-8.

Does SimpleDateFormat support the nu-extension?

Using debugging of following code, I discovered that the nu-extension is only supported for Thai-numerals (see also official javadoc of class java.util.Locale but not for arabic-indic digits:

SimpleDateFormat sdf = 
    new SimpleDateFormat("EEEE d MMMM yyyy - HH:mm", Locale.forLanguageTag("ar-SA-nu-arab"));
Date d = sdf.parse(dateTimeString);
System.out.println(d);
String formatted = sdf.format(d);
System.out.println(formatted);
System.out.println(sdf.format(d).equals(dateTimeString));

sdf = new SimpleDateFormat("EEEE d MMMM uuuu - HH:mm", Locale.forLanguageTag("ar-SA-u-nu-thai"));
String thai = sdf.format(d);
System.out.println("u-nu-thai: " + thai);

I assume the class DateTimeFormatter of Java-8 also supports Thai numerals.

Conclusion:

Forget the nu-extension. Just construct the locale via the old-fashioned way without unicode extension and adapt Oles answer this way. It works because your input only has western digits 0-9.

For extensive i18n-support including the nu-extension for various numbering systems (if you have such input), you might consider external libraries (for example ICU4J or my lib Time4J).

like image 125
Meno Hochschild Avatar answered Oct 29 '22 05:10

Meno Hochschild


Edit: with thanks to slim and Meno Hochschild for inspiration:

String dateTimeString = "الاثنين 24 أبريل 2017 - 15:00";

DateTimeFormatter formatter
        = DateTimeFormatter.ofPattern("EEEE d MMMM uuuu - HH:mm", new Locale("ar"));
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(dateTime);

This prints:

2017-04-24T15:00
like image 37
Ole V.V. Avatar answered Oct 29 '22 06:10

Ole V.V.


I don't know enough Arabic to understand an Arabic formatted date. However this code:

Locale arabicLocale = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build();

LocalDate date = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(arabicLocale);

String formatted = date.format(formatter);
System.out.println(formatted);
System.out.println(formatter.parse(formatted));

Yields this output:

26 أبريل, 2017
{},ISO resolved to 2017-04-26

The code to create the Locale is from an answer to Setting Arabic numbering system locale doesn't show Arabic numbers

You can fine-tune this format by defining your own FormatStyle.

like image 23
slim Avatar answered Oct 29 '22 06:10

slim