Date formatting based on user locale on android

AndroidInternationalizationDate Format

Android Problem Overview


I want to display a date of birth based on the user locale. In my application, one of my fields is the date of birth, which is currently in the format dd/mm/yyyy. So if the user changes his locale, the date format should also change accordingly. Any pointers or code samples would really help me to overcome the problem.

Android Solutions


Solution 1 - Android

You can use the DateFormat class that formats a date according to the user locale.

Example:

String dateOfBirth = "26/02/1974";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = null;
try {
    date = sdf.parse(dateOfBirth);
} catch (ParseException e) {
    // handle exception here !
}
java.text.DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context);
String s = dateFormat.format(date);

You can use the different methods getLongDateFormat, getMediumDateFormat depending on the level of verbosity you would like to have.

Solution 2 - Android

While the accepted answer was correct when the question was asked, it has later become outdated. I am contributing the modern answer.

java.time and ThreeTenABP

	DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
	
	LocalDate dateOfBirth = LocalDate.of(1991, Month.OCTOBER, 13);
	String formattedDob = dateOfBirth.format(dateFormatter);
	System.out.println("Born: " + formattedDob);

It gives different output depending on the locale setting of the JVM (usually taking from the device). For example:

  • Canadian French: Born: 91-10-13
  • Chinese: Born: 1991/10/13
  • German: Born: 13.10.91
  • Italian: Born: 13/10/91

If you want a longer format, you may specify a different format style. Example outputs in US English locale:

  • FormatStyle.SHORT: Born: 10/13/91
  • FormatStyle.MEDIUM: Born: Oct 13, 1991
  • FormatStyle.LONG: Born: October 13, 1991
  • FormatStyle.FULL: Born: Thursday, October 13, 1991

Question: Can I use java.time on Android?

> DateTimeFormatter.ofLocalizedDate requires Api O minimum.

Yes, java.time works nicely on older and newer Android devices. No, it does not require API level 26 or Oreo even though a message in your Android Studio might have you think that. 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 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 either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Question: Can I also accept user input in the user’s local format?

Yes, you can. The formatter can also be used for parsing a string from the user into a LocalDate:

	LocalDate date = LocalDate.parse(userInputString, dateFormatter);

I suggest that you first format an example date and show it to the user so that s/he can see which format your program expects for his/her locale. As example date take a date with day of month greater than 12 and year greater than 31 so that the order of day, month and year can be seen from the example (for longer formats the year doesn’t matter since it will be four digits).

Parsing will throw a DateTimeParseException if the user entered the date in an incorrect format or a non-valid date. Catch it and allow the user to try again.

Question: Can I do likewise with a time of day? A date and time?

Yes. For formatting a time of day according to a user’s locale, get a formatter from DateTimeFormatter.ofLocalizedTime. For both date and time together use one of the overloaded versions of DateTimeFormatter.ofLocalizedDateTime.

Avoid the DateFormat, SImpleDateFormat and Date classes

I recommend you don’t use DateFormat, SimpleDateFormat and Date. Those classes are poorly designed and long outdated, the first two in particular notoriously troublesome. Instead use LocalDate, DateTimeFormatter and other classes from java.time, the modern Java date and time API.

Solution 3 - Android

As simple as

For date + time:

DateFormat format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT, Locale.getDefault());

For just date:

DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());

Solution 4 - Android

To change the date format according to the locale, the following code worked to me:

    String dateOfBirth = "26/02/1974";
	SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	Date date = null;
	try {
		date = sdf.parse(dateOfBirth);
	} catch (ParseException e) {
	    // handle exception here !
	}
	
	String myString = DateFormat.getDateInstance(DateFormat.SHORT).format(date);

Then when you change the locale, the date format will change based on it. For more information about the dates patterns: http://docs.oracle.com/javase/tutorial/i18n/format/dateFormat.html

Solution 5 - Android

Android api provide easy way to display localized date format. The following code works.

public class FileDateUtil {
    public static String getModifiedDate(long modified) {
        return getModifiedDate(Locale.getDefault(), modified);
    }

    public static String getModifiedDate(Locale locale, long modified) {
        SimpleDateFormat dateFormat = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            dateFormat = new SimpleDateFormat(getDateFormat(locale));
        } else {
            dateFormat = new SimpleDateFormat("MMM/dd/yyyy hh:mm:ss aa");
        }

        return dateFormat.format(new Date(modified));
    }
 
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    public static String getDateFormat(Locale locale) {
        return DateFormat.getBestDateTimePattern(locale, "MM/dd/yyyy hh:mm:ss aa");
    }
}

You can check following code.

String koreaData = FileDateUtil.getModifiedDate(Locale.KOREA, System.currentTimeMillis());
String franceData = FileDateUtil.getModifiedDate(Locale.FRENCH, System.currentTimeMillis());
String defaultData = FileDateUtil.getModifiedDate(Locale.getDefault(), System.currentTimeMillis());
     
String result = "Korea : " + koreaData + System.getProperty("line.separator");
result += "France : " + franceData + System.getProperty("line.separator");
result += "Default : " + defaultData + System.getProperty("line.separator"); 
tv.setText(result);

Solution 6 - Android

The simple way to do it:

String AR_Format = "dd-mm-yyyy";
String EN_Format = "mm-dd-yyyy";

String getFomattedDateByLocale(Date date, String locale) {
    return new SimpleDateFormat(strDateFormat, new Locale(locale)).format(date);
}

And then call it like this:

txtArabicDate.setText(getFomattedDateByLocale(new Date(), AR_Format));
txtEnglishDate.setText(getFomattedDateByLocale(new Date(), EN_Format));

Don't forget to replace new Date() by your own date variable.

Good luck.

Solution 7 - Android

To get the date format pattern you can do :

Format dateFormat = android.text.format.DateFormat.getDateFormat(getApplicationContext());
String pattern = ((SimpleDateFormat) dateFormat).toLocalizedPattern();

After that, you can format your input as per the pattern.

Solution 8 - Android

My way, with example: UTC iso format String to android User.

    //string UTC instant to localDateTime
    String example = "2022-01-27T13:04:23.891374801Z"
    Instant instant = Instant.parse(example);
    TimeZone timeZone = TimeZone.getDefault();
    LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, timeZone.toZoneId());

    //localDateTime to device culture string output
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
    String strDate = localDateTime.toLocalDate().format(dateFormatter);
    DateTimeFormatter timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
    String strTime = localDateTime.toLocalTime().format(timeFormatter);

    //strings to views
    txtDate.setText(strDate);
    txtTime.setText(strTime);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionshailbenqView Question on Stackoverflow
Solution 1 - AndroidArnaudView Answer on Stackoverflow
Solution 2 - AndroidOle V.V.View Answer on Stackoverflow
Solution 3 - AndroidDavid_EView Answer on Stackoverflow
Solution 4 - AndroidFelipe R. SaruhashiView Answer on Stackoverflow
Solution 5 - AndroidJustin SongView Answer on Stackoverflow
Solution 6 - AndroidOsama RemlawiView Answer on Stackoverflow
Solution 7 - Androidmanish poddarView Answer on Stackoverflow
Solution 8 - AndroidBarrretttView Answer on Stackoverflow