我注意到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.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提交了两份提交内容:
答案 0 :(得分:17)
我相信' 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"作为March的独立名称。
答案 1 :(得分:4)
根据javadocs:
模式字母' L',' c'和' q'指定文本样式的独立形式。
然而,我无法找到关于#34;独立"形式应该是。在查看代码时,我看到使用' L'根据那个javadoc选择TextStyle.SHORT_STANDALONE
:
独立使用的简短文本,通常是缩写。例如,星期一星期一可能输出"星期一"。
然而,这并不是它的工作方式。即使有三个字母,我也可以从这段代码中获得数字输出:
DateTimeFormatter pattern = DateTimeFormatter.ofPattern ("dd-LLL-yyyy");
System.out.println (pattern.format (LocalDate.now ()));
修改强>
经过进一步调查,似乎(尽可能接近我所知道的)#34;独立"这些代码的版本适用于您希望加载自己的与语言环境无关的数据,可能是使用DateTimeFormatterBuilder
。因此,默认情况下DateTimeFormatter
没有为TextStyle.SHORT_STANDALONE
加载条目。
答案 2 :(得分:1)
虽然其他答案在模式字母L
和日期解析方面提供了很好的信息,但我想补充一点,您应该完全避免这个问题。不要从数据库中获取日期(和时间)作为字符串。而是使用适当的datetime对象。
String sql = "select sysdate as dt from dual;"
PreparedStatement stmt = yourDatabaseConnection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
LocalDateTime dateTime = rs.getObject("dt", LocalDateTime.class);
// do something with dateTime
}
(未经测试,因为我手头没有Oracle数据库。请原谅任何错字。)