Home > Software design >  Weird issue with Month in SimpleDateFormat
Weird issue with Month in SimpleDateFormat

Time:10-05

I tried to format my date time:

Locale locale = context.getResources().getConfiguration().locale;
dateFormatDayMonth = new SimpleDateFormat("EEE, MMM d", locale);
textView.setText(dateFormatDayMonth.format(calendar.getTime()));

However, the result is Sat, M10 2. I expected it to be Sat, Oct 2. It's used to work before, but suddenly it's stopped working. Is there anything I missed here?

CodePudding user response:

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // A dummy Locale for the demo
        Locale localeFromResponse = new Locale("default");

        Locale locale = localeFromResponse.toString().equals("default") ? Locale.getDefault() : localeFromResponse;
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE, MMM d", locale);
        String formatted = OffsetDateTime.now(ZoneOffset.UTC).format(dtf);
        System.out.println(formatted);

        // textView.setText(formatted);
    }
}

Output:

Tue, Oct 5

ONLINE DEMO

If you have an existing java.util.Calendar object

You can convert the existing java.util.Calendar object to java.time.Instant using Calendar#toInstant which can in turn be converted into other Date-Time types of java.time API.

Demo:

import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Dummy Locale and Calendar objects - for the demo
        Locale localeFromResponse = new Locale("default");
        Calendar calendar = Calendar.getInstance();

        Locale locale = localeFromResponse.toString().equals("default") ? Locale.getDefault() : localeFromResponse;
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE, MMM d", locale);
        ZonedDateTime zdt = calendar.toInstant().atZone(ZoneOffset.UTC);
        String formatted = zdt.format(dtf);
        System.out.println(formatted);

        // textView.setText(formatted);
    }
}

Output:

Tue, Oct 5

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.

Just in case you need to do it using the legacy API

For any reason, if you want to stick to the legacy API, you can map the Locale in the same way as I have done above i.e. it will be

Locale localeFromResponse = context.getResources().getConfiguration().locale;

Locale locale = localeFromResponse.toString().equals("default") ? Locale.getDefault() : localeFromResponse;
dateFormatDayMonth = new SimpleDateFormat("EEE, MMM d", locale);
textView.setText(dateFormatDayMonth.format(calendar.getTime()));

* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8 APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time.

CodePudding user response:

Initialize your date format just like this

Locale locale = Locale.getDefault();
    DateFormat dateFormat = new SimpleDateFormat("EEE, MMM d", locale);
    Calendar calendar = Calendar.getInstance(locale);
    outputDate.setText(dateFormat.format(calendar.getTime()));
  • Related