My date is in a string in the format "2013-12-31". I want to convert this to a local date based upon the user's device setting but only show the month and day. So if the user's device is set to German, the date should be converted to "31.12". In Germany, the day comes first followed by the month. I don't want the year to be included.
-
SimpleDateFormat: http://stackoverflow.com/questions/3056703/simpledateformat – Mohsen Afshin Oct 22 '13 at 14:54
-
Nope. That ends up including the year. A year in different locales can be at the start or end of the date. So it's not as easy as it looks. – Johann Oct 22 '13 at 15:15
-
It only includes the year if you include the year in your format. Your question indicates that you don't want the year to display at all, which `SimpleDateFormat` is more than capable of. – Bryan Herbst Oct 22 '13 at 17:41
-
@AndroidDev, please, have a look at my solution. – Ayaz Alifov Jul 21 '16 at 16:03
6 Answers
For Build.VERSION.SDK_INT < 18
I could not find a way to obtain a month/day format that obeys user preferences. This answer works if you are willing to accept month/day in user's locale default pattern (not their preferred order or format). My implementation uses the full numeric format in versions less than 18 or if any issues are encountered in the following carefully programmed series of steps.
- Get user's numeric date format pattern as String
- Reduce pattern to skeleton format without symbols or years
- Obtain localized month/day format with DateFormat.getBestDateTimePattern
- Reorder localized month/day format according to user preferred order. (key assumption: days and months can be naively swapped for all localized numeric formats)
This should result in a month/day pattern that obeys user's preference in localized formatting.
Get user date pattern string per this answer:
java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
if (shortDateFormat instanceof SimpleDateFormat) {
String textPattern = ((SimpleDateFormat) shortDateFormat).toPattern();
}
Reduce pattern to day/month skeleton by removing all characters not 'd' or 'M', example result:
String skeletonPattern = 'ddMM'
Get localized month/day format:
String workingFormat = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeletonPattern);
(note: this method requires api 18 and above and does not return values in user-preferred order or format, hence this long-winded answer):
Get user preferred date order ('M', 'd', 'y') from this method:
char[] order = DateFormat.getDateFormatOrder(context);
(note: I suppose you could parse the original pattern to get this information too)
If workingFormat
is in the correct order, your job is finished. Otherwise, switch the 'd's and the 'M's in the pattern.
The key assumption here is that days and months can be naively swapped for all localized numeric formats.
DateFormat monthDayFormat = new SimpleDateFormat(workingFormat);

- 1
- 1

- 2,764
- 23
- 18
-
Strange, but on some devices DateFormat.getDateFormatOrder() just crashes, so it might be a good idea to cover it with try {} catch (IllegalArgumentException e) {}. – sandrstar Apr 17 '17 at 08:38
I think, this is the simplest solution for apps targeting API > 17:
dateFormat = SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMM dd"), Locale.getDefault())

- 8,285
- 5
- 40
- 53
A bit late, bit I also faced the same issue. That is how I solved it:
String dayMonthDateString = getDayMonthDateString("2010-12-31", "yyyy-MM-dd", Locale.GERMANY);
Log.i("customDate", "dayMonthDateString = " + dayMonthDateString);
private String getDayMonthDateString(String dateString, String dateFormatString, Locale locale)
{
try
{
boolean dayBeforeMonth = defineDayMonthOrder(locale);
String calendarDate = dateString;
SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatString);
Date date = dateFormat.parse(calendarDate);
SimpleDateFormat newDateFormat;
if (dayBeforeMonth)
{
newDateFormat = new SimpleDateFormat("dd.MM", locale);
}
else
{
newDateFormat = new SimpleDateFormat("MM.dd", locale);
}
return newDateFormat.format(date);
}
catch (ParseException e)
{
e.printStackTrace();
}
return null;
}
private boolean defineDayMonthOrder(Locale locale) throws ParseException
{
String day = "10";
String month = "11";
String year = "12";
String calendarDate = day + "." + month + "." + year;
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yy");
Date date = format.parse(calendarDate);
String localizedDate = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT, locale).format(date);
int indexOfDay = localizedDate.indexOf(day);
int indexOfMonth = localizedDate.indexOf(month);
return indexOfDay < indexOfMonth ? true : false;
}
Let me know of any questions you could have related to the solution.

- 8,334
- 4
- 61
- 56
-
@box, thank you. I couldn't find any better solution till now. If you find one, I would be very glad to know. – Ayaz Alifov Jun 08 '17 at 16:10
Keep it simple, we already have a method for this (API 18+):
String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy-MM-dd");
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault());
String output = format.format(currentTimeMs);
Today its 2019 July 18:
In Europe, the output will be
18.07.2019
In the US, the output will be:
07/18/2019

- 6,256
- 2
- 54
- 42
This works:
String dtStart = "2010-12-31";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(dtStart);
SimpleDateFormat df = (SimpleDateFormat)
DateFormat.getDateInstance(DateFormat.SHORT);
String pattern = df.toLocalizedPattern().replaceAll(".?[Yy].?", "");
System.out.println(pattern);
SimpleDateFormat mdf = new SimpleDateFormat(pattern);
String localDate = mdf.format(date);

- 27,536
- 39
- 165
- 279
-
This doesn't work in the case of German month/day format, which is "day.month." (trailing period included) – Rich Ehmer Jan 04 '15 at 15:35
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat outputFormat = new SimpleDateFormat("dd.MM");
try {
Date date = inputFormat.parse("2013-12-31");
String out = outputFormat.format(date);
// out is 31.12
} catch (ParseException e) {
e.printStackTrace();
}

- 13,273
- 10
- 65
- 90
-
2Wrong. You are forcing the period in the formatting as well as the order of the month and day. On an Android device, you ALWAYS use the formatting of the locale which could be a slash, period, space, whatever. You mustn't force the ordering. – Johann Oct 22 '13 at 15:52