Use HH for hour of day instead of hh
The problem that you are asking about is that you are using lowercase hh
in your format pattern string (both times). You need uppercase HH
for hour day from 00 through 23. hh
is for hour within AM or PM from 01 through 12. So what went wrong was that java.time didn’t know whether 12
in your string referred to 12 AM or 12 PM and refused to make a guess for you.
If you read the exception message closely you will also notice that it says that HourOfAmPm=0
was parsed. It doesn’t say HourOfDay
.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String timestampString = LocalDateTime.now().format(formatter);
System.out.println("timestampString: " + timestampString);
Instant instant = LocalDateTime.parse(timestampString, formatter)
.toInstant(ZoneOffset.UTC);
System.out.println("instant: " + instant);
When I ran this snippet just now, I got this output:
timestampString: 2019-06-08 19:22:51
instant: 2019-06-08T19:22:51Z
This is wrong! I ran the snippet around 17:22 UTC, not 19:22. Since Denmark is still using summer time (damn), the local time here was 19:22, which was used for the result and translated into the same wall clock time in UTC, not the same instant. You should always pass your desired time zone to the now
method to avoid such bugs. Since you wanted UTC:
String timestampString = LocalDateTime.now(ZoneOffset.UTC).format(formatter);
timestampString: 2019-06-08 17:27:57
instant: 2019-06-08T17:27:57Z
Still better, don’t use LocalDateTime
for holding something that you want to use as a moment in time. Use Instant
, OffsetDateTime
or ZonedDateTime
instead.
There is more information on using hh
, HH
or kk
for formatting and parsing hour values in this question and its answers: Difference between java HH:mm and hh:mm on SimpleDateFormat. The question is asking about the notoriously troublesome SimpleDateFormat
, but the answers are valid for DateTimeFormatter
too.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…