当前位置: 首页 > 面试题库 >

DateTimeFormatter月模式字母“ L”失败

申浩广
2023-03-14
问题内容

我注意到java.time.format.DateTimeFormatter无法按预期解析。见下文:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Play {
  public static void tryParse(String d,String f) {
    try { 
      LocalDate.parse(d, DateTimeFormatter.ofPattern(f)); 
      System.out.println("Pass");
    } catch (Exception x) {System.out.println("Fail");}
  }
  public static void main(String[] args) {
    tryParse("26-may-2015","dd-L-yyyy");
    tryParse("26-May-2015","dd-L-yyyy");
    tryParse("26-may-2015","dd-LLL-yyyy");
    tryParse("26-May-2015","dd-LLL-yyyy");
    tryParse("26-may-2015","dd-M-yyyy");
    tryParse("26-May-2015","dd-M-yyyy");
    tryParse("26-may-2015","dd-MMM-yyyy");
    tryParse("26-May-2015","dd-MMM-yyyy");
  }
}

只有最后一次尝试tryParse("26-May-2015","dd-MMM- yyyy");才会“通过”。按照文档,LLL应该能够解析出文本格式。还要注意大写字母“ M”与小写字母“ m”的细微差别。

这真的很烦人,因为我默认情况下无法解析Oracle DB默认设置格式的字符串

SELECT TO_DATE(SYSDATE,'DD-MON-YYYY') AS dt FROM DUAL;

同样,对于以下程序:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Play {
  public static void output(String f) {
    LocalDate d = LocalDate.now();
    Locale l = Locale.US;
    // Locale l = Locale.forLanguageTag("ru");
    System.out.println(d.format(DateTimeFormatter.ofPattern(f,l)));
  }
  public static void main(String[] args) {
    output("dd-L-yyyy");
    output("dd-LLL-yyyy");
    output("dd-M-yyyy");
    output("dd-MMM-yyyy");
  }
}

我得到以下输出:

28-5-2015
28-5-2015
28-5-2015
28-May-2015

显然,L格式说明符不处理任何文本内容,对我而言似乎是数字…

但是,如果将Locale更改为,则会Locale.forLanguageTag("ru")得到以下输出:

28-5-2015
28-Май-2015
28-5-2015
28-мая-2015

真的很有趣,您不同意吗?

我的问题是:

  • 我期望每个工具都能正常工作是否合理?
  • 我们至少应该将其中一些提交为错误吗?
  • 我是否误解了L模式说明符的用法。

引用我认为“很重要”的文档的一部分:

文字: 文字样式取决于所使用的图案字母的数量。少于4个图案字母将使用缩写形式。恰好4个图案字母将使用完整格式。恰好5个图案字母将使用窄幅形式。
模式字母“ L”,“ c”和“ q”指定文本样式的独立形式

数字:
如果字母数为1,则使用最少的数字位数输出该值,并且不带填充。否则,将数字的计数用作输出字段的宽度,并在必要时将值补零。以下图案字母对字母数有限制。只能指定一个字母“
c”和“ F”。最多可以指定两个字母“ d”,“ H”,“ h”,“ K”,“ k”,“ m”和“ s”。最多可以指定三个字母“ D”。

数字/文字: 如果图案字母的数量为3个或更多,请使用上面的文字规则 。否则,请使用上面的数字规则。

更新

我已经向Oracle提交了两份意见书:

  • 要求为LLL(长格式文本)问题修正错误:JDK-8114833(原始oracle审阅ID:JI-9021661)
  • 要求增强小写月份解析问题:审查ID:0(这也是一个错误吗?)

问题答案:

我认为“ L”是指月份本身与日期中使用不同单词的语言。例如:

Locale russian = Locale.forLanguageTag("ru");

asList("MMMM", "LLLL").forEach(ptrn -> 
    System.out.println(ptrn + ": " + ofPattern(ptrn, russian).format(Month.MARCH))
);

输出:

MMMM: марта
LLLL: Март

解析日期时,不应有任何理由使用“ L”代替“ M”。

我尝试了以下操作,以查看哪些语言环境支持独立的月份名称格式:

Arrays.stream(Locale.getAvailableLocales())
    .collect(partitioningBy(
                loc -> "3".equals(Month.MARCH.getDisplayName(FULL_STANDALONE, loc)),
                mapping(Locale::getDisplayLanguage, toCollection(TreeSet::new))
    )).entrySet().forEach(System.out::println);

以下语言从“ LLLL”获取特定于语言环境的独立月份名称:

加泰罗尼亚语,中文,克罗地亚语,捷克语,芬兰语,希腊语,匈牙利语,意大利语,立陶宛语,挪威语,波兰语,罗马尼亚语,俄语,斯洛伐克语,土耳其语,乌克兰语

所有其他语言在3月的独立名称中均获得“ 3”。



 类似资料:
  • 只有对的最后一次尝试才会“通过”。根据文档,应该能够解析出文本格式。还要注意大写的'm'和小写的'm'之间的细微差别。 这真的很烦人,因为我无法在默认情况下解析出Oracle DB默认格式化的字符串 同样,对于以下程序: 我的问题是: 对我来说,期望每一个都能工作是合理的吗? 我们至少应该将其中一些作为bug提交吗? 我是否误解了模式说明符的用法。 引用文档中的一个部分,我称之为“它很重要”: 针

  • 我有以下行在我的代码,我试图格式化一个日期字符串 在第2行,我得到了这个错误: 如何为将给出例如:

  • 运行下面列出的代码时,我看到以下错误: 线程“main”java中出现异常。时间总体安排DateTimeParseException:无法在java的索引4处分析文本“2017年9月21日星期四23:47:03 EDT”。时间总体安排DateTimeFormatter。java上的parseResolved0(未知源)。时间总体安排DateTimeFormatter。在java上解析(未知源)。时

  • 问题内容: 是否可以从Joda-Time DateTimeFormatter获取模式字符串? 问题答案: Joda Time无法提供从DateTimeFormatter获取原始模式的方法。原因之一可能是DateTimeFormatter不一定是从模式创建的。例如根本不使用模式。 但是,如果您始终使用模式,则可以包装该类以在构建时记录模式。这样,您以后可以使用简单的静态方法进行查找。例如: 然后,您

  • 问题内容: 当我使用上面的语句时,我没有得到错误(我没有使用结尾),但是当我使用下面的语句时,我得到了这个错误: int类型的文字3244444444超出范围 如果使用,则没有错误。 这是什么原因呢?对于长变量,不强制使用l。 问题答案: 被解释为文字整数,但不适合32位变量。它必须是一个 字面量long值 ,因此它需要一个or或末尾: 更多信息: 原始数据类型,特别是 默认值 和 文字 部分。

  • 如果偏移量为4位(-05:00),我可以使用:,但这不适用于3位。 有什么想法吗?