SimpleDateFormat - формат - Месяц Сентябрь - JDK16

Я только что обновил Java с JDK-15 до JDK-16 и вижу проблему при преобразовании Date с использованием SimpleDateFormat. Только сентябрьский месяц при форматировании с использованием yyyy-MMM-dd дает 4 символа вместо 3.

Например: 2021-Sep-11 отображается как 2021-Sept-11

          Calendar cal = Calendar.getInstance();
    cal.add(Calendar.DATE, 150);
    SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MMM-dd");
    System.out.println(cal.getTime());

    String formatted = format1.format(cal.getTime());
    System.out.println(formatted);

Мне кажется, это ошибка. Я не вижу никаких обновлений для этого в примечаниях к выпуску. Кто-нибудь сталкивается с подобной проблемой? Работал нормально до JDK-15.

2 ответа

Решение

Никогда не используйте тип форматирования / синтаксического анализа даты и времени, потому что тексты Locale-чувствительный.

      import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, 150);
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MMM-dd", Locale.ENGLISH);
        System.out.println(cal.getTime());

        String formatted = format1.format(cal.getTime());
        System.out.println(formatted);
    }
}

Выход:


Обратите внимание, что java.util API даты и времени и их API форматирования, SimpleDateFormatустарели и подвержены ошибкам. Рекомендуется полностью отказаться от них и перейти на java.time, современный API даты и времени*.

Используя современный API даты и времени:

      import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Change ZoneId as per your requirement e.g. ZoneId.of("Europe/London")
        LocalDate date = LocalDate.now(ZoneId.systemDefault());
        date = date.plusDays(150);
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MMM-dd", Locale.ENGLISH);
        String formatted = dtf.format(date);
        System.out.println(formatted);
    }
}

Выход:

      2021-Sep-11

Отметьте этот ответ, чтобы узнать больше о u против y.

Узнайте больше о современном API даты и времени из Trail: Date Time .


* По любой причине, если вам нужно придерживаться Java 6 или Java 7, вы можете использовать ThreeTen-Backport, который поддерживает большую часть функциональности java.time для Java 6 и 7. Если вы работаете над проектом Android и своим Android API уровень по-прежнему не соответствует Java-8, проверьте API-интерфейсы Java 8+, доступные через десугаринг, и Как использовать ThreeTenABP в Android Project .

Вот его версия, которая останется в сентябре:

      final Calendar cal = Calendar.getInstance();
/**/           cal.set(2021, Calendar.SEPTEMBER, 11, 23, 59, 59);

final String           pattern = "yyyy-MMM-dd LL LLL EEE EEEE";
final SimpleDateFormat format1 = new SimpleDateFormat(pattern);

System.out.println("Locale..: " + Locale.getDefault());
System.out.println("Calendar: " + cal.getTime());
System.out.println("Pattern.: " + pattern + " -> " + format1.format(cal.getTime()));

System.out.println("Vendor..: " + ManagementFactory.getRuntimeMXBean().getVmVendor());
System.out.println("VM......: " + ManagementFactory.getRuntimeMXBean().getVmName());
System.out.println("Version.: " + ManagementFactory.getRuntimeMXBean().getSpecVersion());
System.out.println("Build...: " + ManagementFactory.getRuntimeMXBean().getVmVersion());

В немецкой системе он производит для меня следующие выходные данные:

      Locale..: de_DE
Calendar: Sat Sep 11 23:59:59 CEST 2021
Pattern.: yyyy-MMM-dd LL LLL EEE EEEE -> 2021-Sept.-11 09 Sep Sa. Samstag
Vendor..: Oracle Corporation
VM......: Java HotSpot(TM) 64-Bit Server VM
Version.: 16
Build...: 16+36-2231

а также

      Locale..: de_DE
Calendar: Sat Sep 11 23:59:59 CEST 2021
Pattern.: yyyy-MMM-dd LL LLL EEE EEEE -> 2021-Sep-11 09 Sep Sa Samstag
Vendor..: Oracle Corporation
VM......: Java HotSpot(TM) 64-Bit Server VM
Version.: 1.8
Build...: 25.40-b25

Здесь SimpleDateFormat также произвел другое форматирование для месяца, но Spec. немного расплывчато. Он говорит:

«Месяц: если количество шаблонных букв составляет 3 или более, месяц интерпретируется как текст»

Пока все хорошо, но "текст" квалифицируется следующим образом ...

«Текст: для форматирования, если количество букв шаблона равно 4 или более, используется полная форма; в противном случае используется короткая или сокращенная форма, если таковая имеется».

Но для нашего примера с тремя буквами шаблона, что это за краткая форма, не ясно.

Но, может быть, «L» поможет с названием месяца?

Другие вопросы по тегам