问题
I am attempting to capture the time before and after I check a timestamp value on a webpage and then confirm my timestamp falls in between those times. However, I'm struggling to convert my String timestamp into a comparable format in a clean way.
Instant b4 = Instant.now();
//My code submites a file that then triggers the timestamp. I retrieve it as a string
//exa string"9/25/2020, 11:03:18 AM"
DateTimeFormatter dtf = DateTimeFormatter
.ofPattern("MM/dd/yyyy, HH:mm:ss a")
.withZone(ZoneId.systemDefault());
Instant instantTimestamp = Instant.from(dtf.parse(timeStamp));
Instant after = Instant.now();
if (instantTimestamp.isAfter(b4) && instantTimestamp.isBefore(after)) {
testPass = true;
}
Assert.assertTrue(testPass);
My Error: java.time.format.DateTimeParseException: Text '9/25/2020, 12:46:00 PM' could not be parsed at index 0
回答1:
There is a mismatch in the format for the month and its value in the string. The format is MM
which specifies two digits but the value is 9
which is a single digit. You can use single letters for month, day, year, hour, minute, seconds etc. to accommodate all allowable number of digits. Also, I suggest you parse it in a case-insensitive way so that upper and lower case (e.g. AM
and am
) both can be accommodated.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Given date-time string
String dateTimeString = "9/25/2020, 12:46:00 PM";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("M/d/u, H:m:s a")
.toFormatter(Locale.ENGLISH);
// Convert the given date-time string to LocalDateTime
LocalDateTime ldt = LocalDateTime.parse(dateTimeString, dtf);
System.out.println(ldt);
//Convert to LocalDateTime Instant if required
Instant instant=ldt.toInstant(ZoneOffset.UTC);
System.out.println(instant);
}
}
Output:
2020-09-25T12:46
2020-09-25T12:46:00Z
回答2:
The error is due to the format string being used. "MM" requires the month portion of the input string to be exactly two digits long, but "9" is only one digit. In other words, it works for "09/25/2020, 11:03:18 AM", but not for "9/25/2020, 11:03:18 AM".
What's needed here is "M", which doesn't require the value to be preceded by "0":
DateTimeFormatter dtf = DateTimeFormatter
.ofPattern("M/dd/yyyy, HH:mm:ss a")
.withZone(ZoneId.systemDefault());
If the date should also be allowed to be a single digit and not 0-padded for days 0-9, the "M/d/yyyy, HH:mm:ss a"
pattern should be used instead.
This is described the DateTimeFormatter Javadocs:
All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined:
Symbol Meaning Presentation Examples ------ ------- ------------ ------- [...] M/L month-of-year number/text 7; 07; Jul; July; J [...]
Text: [...]
Number: If the count of letters is one, then the value is output using the minimum number of digits and without padding. Otherwise, the count of digits is used as the width of the output field, with the value zero-padded as necessary. [...]
Number/Text: If the count of pattern letters is 3 or greater, use the Text rules above. Otherwise use the Number rules above.
Since "M" uses the "number/text" presentation, and the count of its letters your format ("MM") is 2, then it requires exactly two digits for the month. Switching it to a single "M" causes it to use the minimum number of digits (one digit for months 1-9, and two digits for months 10-12).
来源:https://stackoverflow.com/questions/64068677/timestamp-cant-be-parsed-issue-java-time-format-datetimeparseexception-text-9