我正在尝试解析以下类型的日期:Dec 12 2001 11:59:59PM
。
如果AM / PM不在秒的旁边,我将使用以下模式:MMM dd yyyy HH:mm:ss a
。
然而,使用模式MMM dd yyyy HH:mm:ssa
忽略AM / PM(因此始终将其解释为AM)。
我正在尝试使用SimpleDateFormat
。我试图指定一个区域设置无济于事。
这可能是使用SimpleDateFormat
还是我需要使用替代方法/外部处理? SimpleDateFormat
由于在@JsonFormat
注释的模式属性中的使用而特别感兴趣。
感谢。
答案 0 :(得分:4)
我想使用Java8 +中的java.time
API而不是旧日期:
String date = LocalDateTime.now().format(
DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm:ssa", Locale.ENGLISH)
);
或:
DateTimeFormatter format = DateTimeFormatter.ofPattern(
"MMM dd yyyy hh:mm:ssa", Locale.ENGLISH
);
String date = LocalDateTime.of(2001, Month.DECEMBER, 12, 11, 59, 59).format(format);
<强>输出强>
Jun 14 2018 03:01:02PM
Dec 12 2001 11:59:59AM
答案 1 :(得分:2)
使用AM / PM您需要12小时hh
而不是24小时HH
。
hh:mm:ss''a
由于k/K/h/H影响a
,现在一切都可以与ssa
一起使用。
如果ssa
仍有问题(似乎是一个错误),请尝试用空文字字符串(单引号)分隔字母。
以下作品:
hh:mm:ssa
答案 2 :(得分:2)
使用SimpleDateFormat
可能很有可能,但您可能更愿意使用现代Java日期和时间API java.time
:
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("MMM dd uuuu hh:mm:ssa", Locale.ENGLISH);
String dateTimeString = "Dec 12 2001 11:59:59PM";
LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
System.out.println(dateTime);
输出:
2001-12-12T23:59:59
正如其他人所说,你的问题不在于秒与AM / PM标记之间缺少空间,而是在小时内使用大写HH
。大写HH
表示从00到23的一天中的小时,其中您想要的是小时hh
小时内AM或PM从01到12小时。
正如其他人所说,使用SimpleDateFormat
及其朋友Date
时存在问题:
SimpleDateFormat
尤其以麻烦而闻名。您的经历很典型,当然也不少见。SimpleDateFormat
获取正确的结果要求JVM时区设置与字符串中理解的时区一致,或者将SimpleDateFormat
的时区设置为相关时区。前者很难保证,因为时区设置可以随时从程序的其他部分或在同一JVM中运行的其他程序进行更改。这也意味着如果您确实需要过时的Date
类的实例(例如,对于您不想立即更改的旧API),则需要确定时区转换。然后转换为例如:
Instant inst = dateTime.atZone(ZoneId.of("America/Metlakatla")).toInstant();
Date oldfashionedDate = Date.from(inst);
System.out.println(oldfashionedDate);
我毫不犹豫地向您展示输出,因为Date
在这里显示了一个非常令人惊讶的行为。
Thu Dec 13 08:59:59 CET 2001
8时59分? 12月 13 ?转换为您提供了正确的时间点。当我打印Date
时,会调用其toString
方法。这反过来使用我的JVM的时区设置来生成字符串,因此输出与转换发生的时区完全不同。很明显,当它在Metlakatla的23:59时,它已经是哥本哈根第二天的08:59(我的时区;输出中的CET是中欧时间)。如果我的JVM的时区设置也是America / Metlakatla,那么输出会与预期达成一致:
Wed Dec 12 23:59:59 AKST 2001
您要求SimpleDateFormat
做的是解析第11天和下午1点的时间。这实际上是自相矛盾的,因为PM仅在第12天的小时开始。因此,期望来自请求的异常是合理的。标准设置的SimpleDateFormat
并不能满足您的要求。 SimpleDateFOrmat
非常典型地给你一个错误的结果并假装一切都很好。但是,让我们暂时尝试使用格式模式字符串MMM dd yyyy HH:mm:ssa
的现代代码。然后我们得到:
线程“main”中的异常java.time.format.DateTimeParseException: 文本'Dec 12 2001 11:59:59 PM'无法解析:发现冲突: Field AmPmOfDay 0与源自11:59:59的AmPmOfDay 1不同
我并不是说我完全明白为什么会这样说,但它提到了AM / PM中的冲突,这正是我们所拥有的。
我一开始并没有想过我会给出一个答案,但最后我一方面被bohemian’s comment挑起,只有Joop Eggen的回答是正确的,另一方面是几个{ {3}}声称您无法使用Joop Eggen正在使用的SimpleDateFormat
。所以我想把事情做好。
comments by Basil Bourque解释如何使用java.time
。
答案 3 :(得分:1)
Java内部使用构建器模式。这稍微修改了DateTimeFormatter.RFC_1123_DATE_TIME
的源代码:
我建议不要使用替代方法DateTimeFormatter.ofPattern()
,但在某些可能遇到ofPattern
限制的情况下,它可以证明更强大。
Map<Long, String> moy = new HashMap<>();
moy.put(1L, "Jan"); moy.put(2L, "Feb"); moy.put(3L, "Mar");
moy.put(4L, "Apr"); moy.put(5L, "May"); moy.put(6L, "Jun");
moy.put(7L, "Jul"); moy.put(8L, "Aug"); moy.put(9L, "Sep");
moy.put(10L, "Oct"); moy.put(11L, "Nov"); moy.put(12L, "Dec");
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendText(MONTH_OF_YEAR, moy)
.appendLiteral(' ')
.appendValue(DAY_OF_MONTH, 2)
.appendLiteral(' ')
.appendValue(YEAR, 4, 4, EXCEEDS_PAD)
.appendLiteral(' ')
.appendValue(HOUR_OF_AMPM, 1, 2, NOT_NEGATIVE)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 1, 2, NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 1, 2, NOT_NEGATIVE)
.optionalEnd()
.appendText(AMPM_OF_DAY)
.toFormatter();
System.out.println(format.parse("Jun 14 2018 2:51:22AM")); // {},ISO resolved to 2018-06-14T02:51:22
System.out.println(format.parse("Jun 14 2018 2:51:22PM")); // {},ISO resolved to 2018-06-14T14:51:22
答案 4 :(得分:0)
不幸的是,以下代码不准确。永远不会读取AM / PM标记。根据当地时间,假设是AM或PM。
使用以下格式字符串“MMM dd yyyy HH:mm:ssaaa”。
String str = "Jun 14 2018 13:53:19PM";
DateFormat df = new SimpleDateFormat("MMM dd yyyy HH:mm:ssaaa");
try {
Date date = df.parse(str);
System.out.print(df.format(date));
} catch (ParseException e) {
e.printStackTrace();
}