DateTimeFormatter月份模式字母"L"失败

YoY*_*oYo 24 java date java-8 java-time

我注意到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");
  }
}
Run Code Online (Sandbox Code Playgroud)

只有最后一次尝试tryParse("26-May-2015","dd-MMM-yyyy");将"通过".根据文档LLL应该能够解析出文本格式.也不是大写'M'与小写'm'的细微差别.

这真的很烦人,因为我无法默认解析Oracle DB默认格式化的字符串

SELECT TO_DATE(SYSDATE,'DD-MON-YYYY') AS dt FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

同样,对于以下程序:

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");
  }
}
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

28-5-2015
28-5-2015
28-5-2015
28-May-2015
Run Code Online (Sandbox Code Playgroud)

显然L格式说明符不会对待任何文本,对我来说似乎是数字...

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

28-5-2015
28-???-2015
28-5-2015
28-???-2015
Run Code Online (Sandbox Code Playgroud)

一切都很有意思,你不同意吗?

我的问题是:

  • 我期望每一个应该有效吗?
  • 我们至少应该提交一些这样的bug吗?
  • 我是否误解了L模式说明符的用法.

引用我认为"重要"的文档中的一部分:

文本:文本样式基于使用的模式字母数确定.少于4个模式字母将使用简短形式.正好4个模式字母将使用完整形式.正好5个模式字母将使用窄格式.模式字母'L','c'和'q'指定文本样式的独立形式.

Number:如果字母数为1,则使用最小位数输出该值,不进行填充.否则,将使用数字位数作为输出字段的宽度,并根据需要将值填充为零.以下模式字母对字母数量有约束.只能指定一个字母'c'和'F'.最多可以指定两个字母'd','H','h','K','k','m'和's'.最多可以指定三个字母"D".

数字/文本: 如果模式字母的数量为3或更大,请使用上面的文本规则.否则使用上面的数字规则.

UPDATE

我向Oracle提交了两份提交内容:

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

Mis*_*sha 18

"独立"月份名称

我认为'L'适用于本月使用不同单词的语言与日期中使用的语言.例如:

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

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

输出:

MMMM: ?????
LLLL: ????
Run Code Online (Sandbox Code Playgroud)

在解析日期时,不应该有任何理由使用'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);
Run Code Online (Sandbox Code Playgroud)

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

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

所有其他语言都将"3"作为March的独立名称.

  • 来自DateTimeFormatter javadoc:"正好4个模式字母将使用完整形式".例如,`.ofPattern("MMMM").format(Month.DECEMBER)`将生成"December" (3认同)
  • 结果如预期."2015年8月28日"是"2015年5月28日"."28-Май-2015"的意思是"28-月 - 2015年".'M'应该用于将月份格式化为日期的一部分.'L'应该用于自行格式化月份.虽然'L'因为英语和我试过的其他语言而失败,但也许根本不应该使用'L'. (3认同)
  • 正如问题所示,"LLLL"未能用英语生成月份的全名,而是给你一个数字.因此,如果您使用月视图创建日历应用程序并尝试使用"LLLL"来获取月份的特定于语言环境的独立名称,它将正确地为您提供俄语名称,但只会给您一个数字英语. (2认同)

neu*_*aut 6

根据javadocs:

模式字母“ L”,“ c”和“ q”指定文本样式的独立形式。

但是,我对“独立”表单应该是什么一无所知。在查看代码时,我看到使用'L'选择TextStyle.SHORT_STANDALONE并根据该javadoc:

供独立使用的短文本,通常是缩写。例如,星期几星期一可能会输出“星期一”。

但是,这似乎并不起作用。即使使用三个字母,我也会从此代码中获得数值输出:

DateTimeFormatter pattern = DateTimeFormatter.ofPattern ("dd-LLL-yyyy");
System.out.println (pattern.format (LocalDate.now ()));
Run Code Online (Sandbox Code Playgroud)

编辑

经过进一步研究,似乎(据我所知)这些代码的“独立”版本适用于您想加载自己的独立于语言环境的数据(大概使用)DateTimeFormatterBuilder。因此,默认情况下DateTimeFormatter,不会加载任何条目TextStyle.SHORT_STANDALONE

  • @JoD。我已经用一些额外的信息更新了我的答案。希望它会有所帮助,但是似乎您可能只想依赖非独立代码,除非您需要区域设置独立性并准备做一些额外的工作以使事情按您希望的方式工作。 (2认同)
  • @JoD。选择特定的语言环境与语言环境独立性非常相反-您仍然最终会加载所选语言环境的数据(在您的情况下为US),而没有独立的条目。关键是,如果不手动提供它们,就不会得到它们。 (2认同)