无法在 Java 的波兰语语言环境中解析格式为 d MMMM yyyy 的日期

Unable to Parse a date of format d MMMM yyyy in Polish Locale in Java

我尝试在波兰语语言环境中解析格式为 d MMMM yyyy 的日期(2020 年 12 月 3 日),但无法解析。但是为什么相同的解析在英语等任何其他语言环境中都能正常工作。下面是不起作用的代码示例。有人可以帮忙吗?

    Locale loc = new Locale("pl", "PL");
    String date = "3 December 2020";
    SimpleDateFormat sdFormat =
            new SimpleDateFormat("d MMMM yyyy", loc);
    sdFormat.setLenient(false);
    try {
        Date d = sdFormat.parse(date);
        System.out.println(d);
    } catch (ParseException e) {
        e.printStackTrace();
    }

当试图确定解析问题时,总是做相反的事情,即生成输出,看看解析的输入应该是什么样子。这是一项对所有解析相关问题都非常有用的技术,无论是解析日期字符串、XML 文档、JSON 文本等

因此,我们尝试打印具有给定格式的日期值,以查看解析时的期望值:

Locale loc = new Locale("pl", "PL");
SimpleDateFormat sdFormat = new SimpleDateFormat("d MMMM yyyy", loc);
sdFormat.setLenient(false);

Calendar cal = Calendar.getInstance(loc);
cal.clear();
cal.set(2020, Calendar.DECEMBER, 3);
System.out.println(sdFormat.format(cal.getTime()));

在 Java 7 中,我得到 3 grudzień 2020
在 Java 8、9、11 和 14 中,我得到 3 grudnia 2020

如果你想解析 3 December 2020,那么使用例如Locale.ENGLISH.

您似乎对解析格式化感到困惑。

由于您在 English 中输入日期字符串,您需要使用 Locale.ENGLISH 进行解析 并且您需要另一个 SimpleDateFormat 实例Locale("pl", "PL")将获得的java.util.Date对象格式化new Locale("pl", "PL").

演示:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        Locale loc = new Locale("pl", "PL");
        String date = "3 December 2020";
        SimpleDateFormat sdfForParsing = new SimpleDateFormat("d MMMM yyyy", Locale.ENGLISH);
        SimpleDateFormat sdfForFormatting = new SimpleDateFormat("d MMMM yyyy", loc);
        sdfForParsing.setLenient(false);
        try {
            Date d = sdfForParsing.parse(date);
            System.out.println(d);
            String localiseByPolish = sdfForFormatting.format(d);
            System.out.println(localiseByPolish);

        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

输出:

Thu Dec 03 00:00:00 GMT 2020
3 grudnia 2020

我相信您已经知道日期时间对象仅存储日期时间信息*1并且不存储格式信息。在打印时,日期时间对象打印由其 class 的 toString 实现返回的字符串。此外,java.util.Date 对象 不代表真正的日期时间 class 因为它只存储毫秒(例如 new Date() 对象被实例化为January 1, 1970, 00:00:00 GMT) 的毫秒数,当你打印它时,它会计算你的 JVM 时区中的日期时间并打印相同的时间,即如果你在世界任何地方的给定时刻执行以下两行,

Date date = new Date();
System.out.println(date.getTime());

你会得到相同的号码。检查 以获得演示。

java.util 的日期时间 API 及其格式 API、SimpleDateFormat 已经过时,并且由于有太多此类黑客攻击,它们很容易出错。建议完全停止使用它们并切换到 modern date-time API. Learn more about the modern date-time API at Trail: Date Time.

注意:如果您正在为Android项目工作并且您的AndroidAPI级别仍然不符合Java-8,勾选Java 8+ APIs available through desugaring and .

使用现代日期时间 API:

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

public class Main {
    public static void main(String args[]) {
        Locale loc = new Locale("pl", "PL");
        String date = "3 December 2020";
        DateTimeFormatter dtfForParsing = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ENGLISH)
                                            .withResolverStyle(ResolverStyle.LENIENT);
        DateTimeFormatter dtfForFormatting = DateTimeFormatter.ofPattern("d MMMM yyyy", loc);
        LocalDate localeDate = LocalDate.parse(date, dtfForParsing);
        System.out.println(localeDate);
        String localiseByPolish = localeDate.format(dtfForFormatting);
        System.out.println(localiseByPolish);
    }
}

输出:

2020-12-03
3 grudnia 2020

*1 modern date-time API store also the timezone information. Check Overview 了解更多关于这些 class 的信息。