Reputation: 39
I don't know why there is no error. The code is
String datestr = "2021-01-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
try {
System.out.println(sdf.parse(datestr));
} catch (ParseException e) {
e.printStackTrace();
}
Since the date string, 2021-01-01
, does not match the format pattern string, yyyy-MM
, I had expected and wanted an exception.
The console prints Fri Jan 01 00:00:00 CST 2021
.
The opposite situation does result in an exception as expected. I make code look like this
String datestr = "2021-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
System.out.println(sdf.parse(datestr));
} catch (ParseException e) {
e.printStackTrace();
}
The console prints an error msg: Unparseable date: "2021-01"
Who can tell me why?
Upvotes: 0
Views: 576
Reputation: 53694
Others have already mentioned why this happens (the java parsers stop parsing when they get all they need) and have also explained that this API is older and not as ergonomic. That said, you can do what you want using the ParsePosition
class.
String datestr = "2021-01-01";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
ParsePosition pp = new ParsePosition(0);
sdf.parse(datestr, pp);
if(pp.getIndex() < dateStr.length()) {
throw new ParseException("Parsing failed...");
}
Upvotes: 1
Reputation: 86286
Here’s a modest supplement. Basil Bourque has already shown the good and modern solution to the work you are doing, and Generous Badger has explained why your code didn’t behave the way you had expected.
The code by Basil Bourque does throw the expected exception if you feed a string in the wrong format into each of the code examples. For the modern version of the code you were asking about:
String datestr = "2021-01-01";
YearMonth.parse(datestr);
The result is an:
Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-01-01' could not be parsed, unparsed text found at index 7
Please also enjoy how precise the exception message is.
The same thing happens if you choose to use an explicit formatter:
YearMonth.parse(datestr, DateTimeFormatter.ofPattern("uuuu-MM"));
Exception in thread "main" java.time.format.DateTimeParseException: Text '2021-01-01' could not be parsed, unparsed text found at index 7
There are a lot of confusing and ill-designed traits of SimpleDateFormat
, the class that you tried to use in your two code examples. You have been hit by just of two of them:
Upvotes: 1
Reputation: 338740
Your formatting pattern must fit your input text. In the first case, "2021-01-01"
does not match "yyyy-MM"
. In the second case, "2021-01"
does not match "yyyy-MM-dd"
.
Use java.time classes instead, as wrestling with legacy classes SimpleDateFormat
& Date
is unwise. Simpler too, with no need of formatting patterns.
YearMonth
.from(
LocalDate.parse( "2021-01-01" )
)
.toString()
See this code run live at IdeOne.com.
2021-01
And parsing year-month:
YearMonth.parse( "2021-01" )
You are using terrible date-time classes that were years ago supplanted by the modern java.time classes. Sun, Oracle, and the JCP community gave up on those closes with the unanimous adoption of JSR 310.
Your inputs happen to use standard ISO 8601 formats. The java.time classes use these formats by default when parsing/generating text. So no need to specify a formatting pattern.
LocalDate ld = LocalDate.parse( "2021-01-01" ) ;
YearMonth ym = YearMonth.from( ld ) ;
String output = ym.toString() ;
As for parsing an input of "2021-01"
:
YearMonth ym = YearMonth.parse( "2021-01" ) ;
Upvotes: 2
Reputation: 421
You are describing two different scenarios:
#1 is not an error, since parse(String)
is explicitly documented to just read from the beginning of the input until it has enough:
The method may not use the entire text of the given string.
#2 is an error, because you the pattern says it expects extra data (namely a -
followed by a day) and that data is missing.
Upvotes: 2