Search code examples
javadateformatlocale

Java DateFormat/SimpleDateFormat with Locale (show just day in month and month)


I have a multicultural application, the project uses Java 7. I need to show the date, but the day in month and month only. So for example in Locale.UK today's date looks like: 24/01, but in Locale.US like: 1/24. How to achieve this in Java 7? I tried to use DateFormat.getDateInstance(dateFormat, locale), but in this case I can use just predefined date formats, for example DateFormat.SHORT, DateFormat.DEFAULT etc. there is no predefined format just with the day in month and month only. Next I tried to use SimpleDateFormat with locale, but this is not working as I wonder, it just translates some text according to the locale. Here is my sample code:

DateFormat dfuk = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
DateFormat dfus = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
System.out.println(dfuk.format(new Date()));  // 24/01/17
System.out.println(dfus.format(new Date()));  // 1/24/17
SimpleDateFormat sdfuk = new SimpleDateFormat("dd/MM", Locale.UK);
SimpleDateFormat sdfus = new SimpleDateFormat("dd/MM", Locale.US);
System.out.println(sdfuk.format(new Date()));  // 24/01
System.out.println(sdfus.format(new Date()));  // 24/01

I expected last line to print 01/24 (or 1/24). How to achieve this?


Solution

  • Change your third last line to

    SimpleDateFormat sdfus = new SimpleDateFormat("MM/dd", Locale.US);
    

    Overcoming the shortcoming of what standard Java offers:

    The getDateInstance() method takes an argument for style. The shortest style seems to be DateFormat.SHORT. You can argue that perhaps they should provide one that is even shorter (DateFormat.SHORTER perhaps?) c.f.

    http://docs.oracle.com/javase/6/docs/api/java/text/DateFormat.html#getDateInstance(int)

    Before that happen, you can build an enum of pattern for the shorter style. Below is an example:

    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    
    enum PatternShorter { // or PatternMonthDayOnly
        MM_SLASH_DD     ("MM/dd")
        , DD_SLASH_MM   ("dd/MM")
        ;
        private String pattern;
    
        public String getPattern() {
            return pattern;
        }
    
        private PatternShorter(String pattern) {
            this.pattern = pattern;
        }
    
        public static PatternShorter getDefault() { return DD_SLASH_MM; }
    }
    
    public class DateFormatEx {
        private static Map<Locale, PatternShorter> patternShorter = new HashMap<>();
    
        static {
            patternShorter.put(Locale.UK, PatternShorter.DD_SLASH_MM);
            patternShorter.put(Locale.UK, PatternShorter.MM_SLASH_DD);
            // any locale not listed here will get the default pattern
        }
    
        private static String getPattern (Locale locale) {      
            if (patternShorter.get(locale)!=null) {
                return patternShorter.get(locale).getPattern();
            } else {
                return PatternShorter.getDefault().getPattern();
            }
        }
    
        public static void main(String[] args) {
            List<Locale> listOfLocale = Arrays.asList(Locale.UK, Locale.US, Locale.FRENCH);
            for (Locale locale : listOfLocale) {
                SimpleDateFormat fmt 
                = new SimpleDateFormat(getPattern(locale), locale);
                System.out.format("for locale %s the shorter date/month display is: %s%n"
                        , locale.toString()
                        , fmt.format(new Date()));  
            }
        }
    
    }
    

    The output would be:

    for locale en_GB the shorter date/month display is: 01/24
    for locale en_US the shorter date/month display is: 24/01
    for locale fr the shorter date/month display is: 24/01