【问题标题】:Unable to Parse a date of format d MMMM yyyy in Polish Locale in Java无法在 Java 的波兰语语言环境中解析格式为 d MMMM yyyy 的日期
【发布时间】:2020-12-04 04:19:48
【问题描述】:

我尝试在波兰语语言环境中以 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();
    }

【问题讨论】:

标签: java date locale date-format polish


【解决方案1】:

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

由于您在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不存储格式信息。在打印时,日期时间对象打印其类的 toString 实现返回的字符串。此外,java.util.Date 对象不代表真正的日期时间类,因为它只存储毫秒(例如,new Date() 对象是用来自January 1, 1970, 00:00:00 GMT 的毫秒数实例化的)并且当您打印它,它会计算 JVM 时区中的日期时间并打印相同的内容,即如果您在世界任何地方的给定时刻执行以下两行,

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

你会得到相同的号码。查看this answer 以获取演示。

java.util 的日期时间 API 和它们的格式化 API SimpleDateFormat 已经过时,并且由于有很多这样的 hack,它们很容易出错。建议完全停止使用它们并切换到modern date-time API。通过 Trail: Date Time 了解有关现代日期时间 API 的更多信息。

注意:如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

使用现代日期时间 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

*1modern date-time API 还存储时区信息。查看Overview 了解有关这些课程的更多信息。

【讨论】:

    【解决方案2】:

    在尝试确定解析问题时,请始终执行相反的操作,即生成输出,以查看解析的输入应该是什么样子。这是一种对所有解析相关问题都非常有用的技术,无论是解析日期字符串、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.

    【讨论】:

    • OP 已经特别提到"3 December 2020" 作为要处理的日期字符串。您为什么建议更改问题以使其与您的解决方案保持一致?
    • @ArvindKumarAvinash 请阅读答案。现在再次阅读最后一行。如果 OP 想要 "3 December 2020" 解析,那么 OP 不能使用波兰语语言环境,但必须使用例如英语语言环境,这是此答案建议的唯一代码更改。 --- 剩下的是关于如何研究问题的指导,因此 OP 可以决定如何处理它。如果您不了解问题的原因,通常很难解决问题。这有助于您了解失败的方式/原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多