java.time.format.DateTimeParseException for dd-MMM-yy format - java

I am trying for hours now to parse this String to LocalDate and I just can't find where my pattern is wrong.
public void parseDate() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd'-'MMM'-'yy");
LocalDate date = LocalDate.parse("05-Sep-20", formatter);
}
I get the following exception:
java.time.format.DateTimeParseException: Text '05-Sep-20' could not be parsed at index 3
It works fine when using the pattern dd'-'MMMM'-'yy or dd'-'MM'-'yy, but it just won't work for MMM
I used the single quotes around the dash, because otherwise I was getting a parsing exception at a different index.
I am using Java1.8 and java.time

It could be your locale. Try this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd'-'MMM'-'yy", Locale.US);
LocalDate date = LocalDate.parse("05-Sep-20", formatter);
ref: https://stackoverflow.com/a/44928297

Related

How to parse a yyyy-MM-dd HH:mm:ss to Date?

I'm trying to parse a date with the format "" to Date.
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date date = sdf.parse(dateStr);
String = sdf.format(date);
An example of the dateStr is "2020-04-14 16:34:40.0117372".
I get an error when trying to parse the string, but I don't know why.
The error I'm getting is the following:
java.text.ParseException: Unparseable date: "2020-04-14 16:34:40.0117372"
Why can't I parse this date? How can I do it?
You are using "dd/MM/yyyy" for date format, but you should be using "yyyy-MM-dd" (inverse order, and dashes instead of slashes)
Also I suggest you use modern java.time packages and do something like this:
String str = "2020-04-14 16:34:40.0117372";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
Edit: Having 7 digits for milliseconds is correct, first digits for milliseconds and the rest for nanoseconds. strange. Usually you want 3 digits because 1000 milliseconds is a second. You likely have nanoseconds, which should be dealt with by this method.

SimpleDateFormat vs DateTimeFormatter

I have a use case where I have to compare 2 string dates such as
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(dateFormat.parse("2019-07-07").compareTo(dateFormat.parse("2019-07-07 23:59:59"))>0);
The above statement using SimpleDateFormat works perfectly fine, now I try doing it using DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
System.out.println( LocalDate.parse("2019-07-07", formatter).compareTo(LocalDate.parse("2019-07-07 23:59:59", formatter))>=0);
This fails with exception:-
Exception in thread "main" java.time.format.DateTimeParseException: Text '2019-07-07 23:59:59' could not be parsed, unparsed text found at index 10
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
at java.time.LocalDate.parse(LocalDate.java:400)
at com.amazon.payrollcalculationengineservice.builder.EmployeeJobDataBuilder.main(EmployeeJobDataBuilder.java:226)
How can I avoid this using DateTimeFormatter, the Strings which I pass as input can be in any format like yyyy-mm-dd or yyyy-mm-dd hh:mm:ss , I dont want to write explicitly checks for format , so can I do using DateTimeFormatter as I am able to do this using the SimpleDateFormat library.
You can use [] to specify an optional part of the pattern:
DateTimeFormatter.ofPattern("yyyy-MM-dd[ HH:mm:ss]");
Alternatively, use the overload of parse that takes a ParsePosition, which won't try to parse the entire string if not necessary.
var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
var localDate = LocalDate.from(formatter.parse("2019-07-07 23:59:59", new ParsePosition(0)))

error java.time.format.DateTimeParseException: Text '2020-10-16T18:04:59+0300' could not be parsed at index 24

I´m trying to pase the next String using LocalDateTime, but I always get de unparsed text found error:
java.time.format.DateTimeParseException: Text '2020-10-16T18:04:59+0300' could not be parsed at index 24
Need: from 2020-10-16T18:04:59+0300 to 2020-10-16 18:04.
My code:
public String getFormattingData(String sourceData) {
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ''e", Locale.ENGLISH);
DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("dd-MM-yyy HH:mm", Locale.ENGLISH);
LocalDate date = LocalDate.parse("2020-10-16T18:04:59+0300", sourceFormatter);
return newFormatter.format(date);
}
What am I doing wrong?
See the related question: Format a date using the new date time API
The source format you are looking for is: "yyyy-MM-dd'T'HH:mm:ssZ" (as mentioned by #Sweeper in his comment)
If you want the HH:mm in the output format, you need to use a LocalDateTime rather than a LocalDate
The code below works for me:
public String getFormattingData(String sourceData) {
DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ", Locale.ENGLISH);
DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm", Locale.ENGLISH);
LocalDateTime date = LocalDateTime.parse("2020-10-16T18:04:59+0300", sourceFormatter);
return newFormatter.format(date);
result:
16-10-2020 18:04
You just need to correct the date pattern of source date like this:
public static String formatDate(String strDate, String srcPattern, String tgtPattern) {
DateTimeFormatter srcFormatter = DateTimeFormatter.ofPattern(srcPattern, Locale.ENGLISH);
DateTimeFormatter tgtFormatter = DateTimeFormatter.ofPattern(tgtPattern, Locale.ENGLISH);
return tgtFormatter.format(LocalDateTime.parse(strDate, srcFormatter));
}
You can also use SimpleDateFormat:
public static String formatDate(String strDate, String srcPattern,
String tgtPattern) throws ParseException {
SimpleDateFormat srcFormatter = new SimpleDateFormat(srcPattern, Locale.ENGLISH);
SimpleDateFormat tgtFormatter = new SimpleDateFormat(tgtPattern, Locale.ENGLISH);
return tgtFormatter.format(srcFormatter.parse(strDate));
}
And then call it with any pattern that you want:
System.out.println(formatDate("2020-10-16T18:04:59+0300", "yyyy-MM-dd'T'HH:mm:ssZ", "dd-MM-yyy HH:mm"));
Don’t write a method that converts a date and time from a string in one format to a string in a different format. In your program keep dates and times as proper date-time objects. Just like you don’t keep numbers and Boolean values in strings (I hope!) When you receive string input, parse into a date-time object at once. Only when you need to give string output, format into an appropriate string.
When I receive a string containing date, time and UTC offset, like yours does, I prefer to parse it into a OffsetDateTime so I get all the information. It’s easier to throw unneeded information away later than to invent the information that we neglected to parse. Also a LocalDate will not work for your purpose since it doesn’t contain time of day. So you cannot format one into 2020-10-16 18:04 format.
For parsing your string I would use:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral('T')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.appendOffset("+HHmm", "Z")
.toFormatter();
String sourceData = "2020-10-16T18:04:59+0300";
OffsetDateTime dateTime = OffsetDateTime.parse(sourceData, formatter);
System.out.println(dateTime);
Output is:
2020-10-16T18:04:59+03:00
The definition of the formatter is longish but has the advantage of reusing predefined formatters for date and time.
For displaying a formatted date and time to the user, don’t you want to use the user’s time zone rather then the offset that happened to be in the string (+03:00 in your case)?
ZoneId zone = ZoneId.of("Antarctica/South_Pole");
DateTimeFormatter newFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm", Locale.ENGLISH);
String formatted = dateTime.atZoneSameInstant(zone).format(newFormatter);
System.out.println(formatted);
17-10-2020 04:04
What went wrong in your code?
As others have said, yyyy-MM-dd'T'HH:mm:ssZ in your format pattern string for parsing parses your entire date-time string of 2020-10-16T18:04:59+0300 nicely. The ''e at the end of the format pattern is the culprit. This would require an additional single quote (apostrophe) and the number of the day of the week to be present (pattern letter e is for localized day of week). Since Java had successfully parsed 24 chars and then failed to parse an apostrophe, it threw the exception mentioning thst the string could not be parsed at index 24.

2020-04-03 20:17:46 to "yyyy-MM-dd'T'HH:mm:ss" format

Is there any way in java(java.util.* or Joda api ) to convert "2020-04-03 20:17:46" to "yyyy-MM-dd'T'HH:mm:ss"
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.parse("2020-04-03 20:17:46")
its giving java.text.parseException always
Just for the case you are using Java 8 or above, make use of java.time.
See this simple example:
public static void main(String[] args) {
// example datetime
String datetime = "2020-04-03 20:17:46";
// create a formatter that parses datetimes of this pattern
DateTimeFormatter parserDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// then parse the datetime with that formatter
LocalDateTime ldt = LocalDateTime.parse(datetime, parserDtf);
// in order to output the parsed datetime, use the default formatter (implicitly)
System.out.println(ldt);
// or format it in a totally different way
System.out.println(ldt.format(
DateTimeFormatter.ofPattern("EEE, dd. 'of' MMM 'at' hh-mm-ss a",
Locale.ENGLISH)
)
);
}
This outputs
2020-04-03T20:17:46
Fri, 03. of Apr at 08-17-46 PM
Please note that this doesn't consider any time zone or offset, it just represents a date and time consisting of the passed or parsed years, months, days, hours, minutes and seconds, nothing else.
Do not use Date/Time API from java.util.* as most of them are now outdated. Use java.time API instead.
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) throws IOException {
String strDatetime = "2020-04-03 20:17:46";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parsedDate = LocalDateTime.parse(strDatetime, formatter);
System.out.println(parsedDate);
}
}
Output:
2020-04-03T20:17:46
Learn more about DateTimeFormatter at https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
Could this help you? http://tutorials.jenkov.com/java-internationalization/simpledateformat.html
First you need to parse the String with the old format, you will get a Date object. Then Create a new SimpleDateFormat with your new format, then you can format the Date object.
String dateString = "2020-04-03 20:17:46";
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(dateString);
String formattedDate = output.format(date);
It do not work that way directly but if you still want to do it then, here is the process.
Create an object of SimpleDateFormat with pattern "yyyy-MM-dd HH:mm:ss")
use this to parse the string. Ultimately you are going to get date in both cases. Is there any specific reason for using T in pattern for dates which do not contain them?
Use LocalDateTime.
Timestamp timestamp = Timestamp.parse("2020-04-03 20:17:46");
LocalDateTime localDateTime = timestamp.toLocalDateTime();
System.out.println(localDateTime); // 2020-04-03T20:17:46

ParseException when parsing 3 character abbreviated month using SimpleDateFormat

Here is my code,
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date dft = (Date) format.parse("16-MAY-2018 09:30:22:000");
I am getting below exception
java.text.ParseException: Unparseable date: "16-MAY-2018 09:30:22"
What's to be used to parse milliseconds?
The pattern should be MMM because there are three characters in the month.
You should also prefer java.time classes to the ones you're currently using if you're on Java 8 or above:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("dd-MMM-yyyy")
.appendLiteral(' ')
.append(ISO_LOCAL_TIME)
.toFormatter();
LocalDateTime timestamp = LocalDateTime.parse("16-May-2018 09:30:22", formatter);
Use this pattern: dd-MMM-yyyy HH:mm:ss
Date dft = (Date) format.parse("16-05-2018 09:30:22");
OR change it to
SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
you are using dd-MM-yyyy HH:mm:ss, so parsable is
16-05-2018 09:30:22
and if you want 16-MAY-2018 09:30:22 then use
dd-MMM-yyyy HH:mm:ss
"16-MAY-2018 09:30:22" is not parsable with that time format. If you want to parse that you have to change date format to "dd-MMM-yyyy HH:mm:ss". The double M is only for numbered months (so should be 05 for May).
Check the SimpleDateFormat javadoc for more details: here

Categories