Java LocalDateTime parse error [duplicate] - java

This question already has answers here:
How to parse case-insensitive strings with JSR-310 DateTimeFormatter?
(3 answers)
Closed 6 years ago.
Been trying for 4 hours to figure this out.
:This works
String date = "Jul-01-2014 09:10:12";
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));
:This will not
String date = "JUL-01-2014 09:10:12";
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));
Only difference being the month all capitalized. Proper case of Jul works. Neither JUL or jul will work. I also tried pattern of 'LLL' with no luck. What am I missing??

Well apparently I needed to spend 5 hours on this.
While writing an extension to provide a workaround I discovered this.
String date = "01-JUL-2014 09:10:12";
DateTimeFormatterBuilder fmb = new DateTimeFormatterBuilder();
fmb.parseCaseInsensitive();
fmb.append(DateTimeFormatter.ofPattern("dd-MMM-yyyy HH:mm:ss"));
LocalDateTime dt = LocalDateTime.parse(date, fmb.toFormatter());
Works great for all case styles.

It doesn't look like that is supported by the official API.
Symbol Meaning Presentation Examples
------ ------- ------------ -------
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
The only option for month-of-year is there, and it does not explicitly mention any format supporting three capital letter months.
It's not terribly difficult to convert it back into a format that Java can respect though; it involves a wee bit of finagling the date and putting it back into a single String, though.
The solution below isn't as elegant or as clean as using a third party, but the added benefit is that one doesn't have to rely on the third party library for this code at all.
public String transformToNormalizedDateFormat(final String input) {
String[] components = input.split("-");
String month = components[0];
if(month.length() > 3) {
throw new IllegalArgumentException("Was not a date in \"MMM\" format: " + month);
}
// Only capitalize the first letter.
final StringBuilder builder = new StringBuilder();
builder.append(month.substring(0, 1).toUpperCase())
.append(month.substring(1).toLowerCase())
.append("-");
final StringJoiner stringJoiner = new StringJoiner("-");
Arrays.stream(components, 1, components.length).forEach(stringJoiner::add);
builder.append(stringJoiner.toString());
return builder.toString();
}

Try using DateTimeFormatterBuilder and making parser case-insensitive. Don't forget to specify locale. Otherwise month abbreviation might not be parsed by MMM in default locale:
DateTimeFormatter format = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd-MMM-yyyy")
.toFormatter(Locale.ENGLISH);
LocalDate.parse("03-jun-2015", format);

M by definition takes July; Jul; 07. You might want to try (solution being a little ugly):
date = Character.toUpperCase(date.charAt(0)) + date.substring(1).toLowerCase();
LocalDateTime dt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern("MMM-dd-yyyy HH:mm:ss", Locale.US));
Or you can try using WordUtils from apache-commons for capitalize.

Related

Generic date parsing in java

I have date strings in various formats like Oct 10 11:05:03 or 12/12/2016 4:30 etc
If I do
// some code...
getDate("Oct 10 11:05:03", "MMM d HH:mm:ss");
// some code ...
The date gets parsed, but I am getting the year as 1970 (since the year is not specified in the string.) But I want the year as current year if year is not specidied. Same applies for all fields.
here is my getDate function:
public Date getDate(dateStr, pattern) {
SimpleDateFormat parser = new SimpleDateFormat(pattern);
Date date = parser.parse(myDate);
return date;
}
can anybody tell me how to do that inside getDate function (because I want a generic solution)?
Thanks in advance!
If you do not know the format in advance, you should list the actual formats you are expecting and then try to parse them. If one fails, try the next one.
Here is an example of how to fill in the default.
You'll end up with something like this:
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendPattern("ddMM")
.parseDefaulting(YEAR, currentYear)
.toFormatter();
LocalDate date = LocalDate.parse("yourstring", f);
Or even better, the abovementioned formatter class supports optional elements. Wrap the year specifier in square brackets and the element will be optional. You can then supply a default with parseDefaulting.
Here is an example:
String s1 = "Oct 5 11:05:03";
String s2 = "Oct 5 1996 13:51:56"; // Year supplied
String format = "MMM d [uuuu ]HH:mm:ss";
DateTimeFormatter f = new DateTimeFormatterBuilder()
.appendPattern(format)
.parseDefaulting(ChronoField.YEAR, Year.now().getValue())
.toFormatter(Locale.US);
System.out.println(LocalDate.parse(s1, f));
System.out.println(LocalDate.parse(s2, f));
Note: Dates and times are not easy. You should take into consideration that date interpreting is often locale-dependant and this sometimes leads to ambiguity. For example, the date string "05/12/2018" means the 12th of May, 2018 when you are American, but in some European areas it means the 5th of December 2018. You need to be aware of that.
One option would be to concatenate the current year onto the incoming date string, and then parse:
String ts = "Oct 10 11:05:03";
int currYear = Calendar.getInstance().get(Calendar.YEAR);
ts = String.valueOf(currYear) + " " + ts;
Date date = getDate(ts, "yyyy MMM d HH:mm:ss");
System.out.println(date);
Wed Oct 10 11:05:03 CEST 2018
Demo
Note that we could have used StringBuilder above, but the purpose of brevity of code, I used raw string concatenations instead. I also fixed a few typos in your helper method getDate().

Reformatting a Date from DD-MMM-YYYY to YYYYDDMM or YYYYMMDD

I'm trying to use Java 8 to re-format today's date but I'm getting the following error:
java.time.format.DateTimeParseException: Text '09-OCT-2017' could not be parsed:
Unable to obtain LocalDate from TemporalAccessor:
{WeekBasedYear[WeekFields[SUNDAY,1]]=2017, MonthOfYear=10, DayOfYear=9},ISO of type java.time.format.Parsed
Code:
public static String formatDate(String inputDate, String inputDateFormat, String returnDateFormat){
try {
DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern(inputDateFormat).toFormatter(Locale.ENGLISH);
LocalDate localDate = LocalDate.parse(inputDate, inputFormatter);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(returnDateFormat);
String formattedString = localDate.format(outputFormatter);
return formattedString;
} catch (DateTimeParseException dtpe) {
log.error("A DateTimeParseException exception occured parsing the inputDate : " + inputDate + " and converting it to a " + returnDateFormat + " format. Exception is : " + dtpe);
}
return null;
}
I previously tried using SimpleDateFormat, but the problem is my inputDateFormat format is always in uppercase DD-MMM-YYYY, which was giving me incorrect results, so I tried using parseCaseInsensitive() to ignore the case sensitivity.
In the comments you told that the input format is DD-MMM-YYYY. According to javadoc, uppercase DD is the day of year field, and YYYY is the week based year field (which might be different from the year field).
You need to change them to lowercase dd (day of month) and yyyy (year of era). The parseCaseInsensitive() only takes care of the text fields - in this case, the month name (numbers are not affected by the case sensitivity - just because the month is in uppercase, it doesn't mean that the numbers patterns should also be).
The rest of the code is correct. Example (changing the format to yyyyMMdd):
String inputDate = "09-OCT-2017";
DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
// use "dd" for day of month and "yyyy" for year
.appendPattern("dd-MMM-yyyy")
.toFormatter(Locale.ENGLISH);
LocalDate localDate = LocalDate.parse(inputDate, inputFormatter);
// use "dd" for day of month and "yyyy" for year
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
String formattedString = localDate.format(outputFormatter);
System.out.println(formattedString); // 20171009
The output of the code above is:
20171009
Regarding your other comment about not having control over the input pattern, one alternative is to manually replace the letters to their lowercase version:
String pattern = "DD-MMM-YYYY";
DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
// replace DD and YYYY with the lowercase versions
.appendPattern(pattern.replace("DD", "dd").replaceAll("YYYY", "yyyy"))
.toFormatter(Locale.ENGLISH);
// do the same for output format if needed
I don't think it needs a complex-replace-everything-in-one-step regex. Just calling the replace method multiple times can do the trick (unless you have really complex patterns that would require lots of different and complex calls to replace, but with only the cases you provided, that'll be enough).
I hope I got you right.
Formatting a String to LocalDate is acutally pretty simple. Your date format is that here right 09-Oct-2017?
Now you just need use the split command to divide that into a day, month and year:
String[] tempStr = inputDate.split("-");
int year = Integer.parseInt(tempStr[2]);
int month = Integer.parseInt(tempStr[1]);
int day = Integer.parseInt(tempStr[0]);
After that it´s pretty easy to get that to LocalDate:
LocalDate ld = LocalDate.of(year, month, day);
I hope that helps.

Java 8 Timezone conversion when creating java.util.Date [duplicate]

This question already has answers here:
Java program to get the current date without timestamp
(17 answers)
Closed 6 years ago.
I want to create a Date object without a TimeZone (eg : 2007-06-21). Is this possible?
When I use the following method it prints like Thu Jun 21 00:00:00 GMT 2007
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
TimeZone timeZone = TimeZone.getTimeZone("GMT");
timeZone.setDefault(timeZone);
sdf.setTimeZone(timeZone);
Date pickUpDate = sdf.parse("2007-06-21");
System.out.println(pickUpDate);
If you want to format a date, you need to use DateFormat or something similar. A Date is just an instant in time - the number of milliseconds since the Unix epoch. It doesn't have any idea of time zone, calendar system or format. The toString() method always uses the system local time zone, and always formats it in a default way. From the documentation:
Converts this Date object to a String of the form:
dow mon dd hh:mm:ss zzz yyyy
So it's behaving exactly as documented.
You've already got a DateFormat with the right format, so you just need to call format on it:
System.out.println("pickUpDate" + sdf.format(pickUpDate));
Of course it doesn't make much sense in your sample, given that you've only just parsed it - but presumably you'd normally be passing the date around first.
Note that if this is for interaction with a database, it would be better not to pass it as a string at all. Keep the value in a "native" representation for as much of the time as possible, and use something like PreparedStatement.setDate to pass it to the database.
As an aside, if you can possibly change to use Joda Time or the new date/time API in Java 8 (java.time.*) you'll have a much smoother time of it with anything date/time-related. The Date/Calendar API is truly dreadful.
This is the toString() of the java.util.Date
public String toString() {
// "EEE MMM dd HH:mm:ss zzz yyyy";
BaseCalendar.Date date = normalize();
StringBuilder sb = new StringBuilder(28);
int index = date.getDayOfWeek();
if (index == gcal.SUNDAY) {
index = 8;
}
convertToAbbr(sb, wtb[index]).append(' '); // EEE
convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM
CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH
CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
TimeZone zi = date.getZone();
if (zi != null) {
sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz
} else {
sb.append("GMT");
}
sb.append(' ').append(date.getYear()); // yyyy
return sb.toString();
}
So, if you will pass a Date and try to print it this will be printed out all the time.
Code:
Date date = new Date();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
Date : Fri Apr 29 04:53:16 GMT 2016
Sample Output : 2016-04-29
Imports required :
import java.util.Date; //for new Date()
import java.text.SimpleDateFormat; // for the format change
System.out.println("pickUpDate " + sdf.format(pickUpDate));
You can use the above code to get formatted Date as String
Use this Code:
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
Date pickUpDate =sdf.parse("2007-06-21");
System.out.println("pickUpDate "+sdf.format(pickUpDate));
Hope it'll help you.
String your_format_date=sdf.format(pickUpDate);
System.out.println("pick Up Date " + your_format_date);
Date isn't a date. It's a timestamp. That's some impressive API design, isn't it?
The type you need is now java.time.LocalDate, added in Java 8.
If you can't use Java 8, you can use ThreeTen, a backport for Java 7.

How do I create the java date object without time stamp [duplicate]

This question already has answers here:
Java program to get the current date without timestamp
(17 answers)
Closed 6 years ago.
I want to create a Date object without a TimeZone (eg : 2007-06-21). Is this possible?
When I use the following method it prints like Thu Jun 21 00:00:00 GMT 2007
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
TimeZone timeZone = TimeZone.getTimeZone("GMT");
timeZone.setDefault(timeZone);
sdf.setTimeZone(timeZone);
Date pickUpDate = sdf.parse("2007-06-21");
System.out.println(pickUpDate);
If you want to format a date, you need to use DateFormat or something similar. A Date is just an instant in time - the number of milliseconds since the Unix epoch. It doesn't have any idea of time zone, calendar system or format. The toString() method always uses the system local time zone, and always formats it in a default way. From the documentation:
Converts this Date object to a String of the form:
dow mon dd hh:mm:ss zzz yyyy
So it's behaving exactly as documented.
You've already got a DateFormat with the right format, so you just need to call format on it:
System.out.println("pickUpDate" + sdf.format(pickUpDate));
Of course it doesn't make much sense in your sample, given that you've only just parsed it - but presumably you'd normally be passing the date around first.
Note that if this is for interaction with a database, it would be better not to pass it as a string at all. Keep the value in a "native" representation for as much of the time as possible, and use something like PreparedStatement.setDate to pass it to the database.
As an aside, if you can possibly change to use Joda Time or the new date/time API in Java 8 (java.time.*) you'll have a much smoother time of it with anything date/time-related. The Date/Calendar API is truly dreadful.
This is the toString() of the java.util.Date
public String toString() {
// "EEE MMM dd HH:mm:ss zzz yyyy";
BaseCalendar.Date date = normalize();
StringBuilder sb = new StringBuilder(28);
int index = date.getDayOfWeek();
if (index == gcal.SUNDAY) {
index = 8;
}
convertToAbbr(sb, wtb[index]).append(' '); // EEE
convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' '); // MMM
CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':'); // HH
CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
TimeZone zi = date.getZone();
if (zi != null) {
sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz
} else {
sb.append("GMT");
}
sb.append(' ').append(date.getYear()); // yyyy
return sb.toString();
}
So, if you will pass a Date and try to print it this will be printed out all the time.
Code:
Date date = new Date();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
Date : Fri Apr 29 04:53:16 GMT 2016
Sample Output : 2016-04-29
Imports required :
import java.util.Date; //for new Date()
import java.text.SimpleDateFormat; // for the format change
System.out.println("pickUpDate " + sdf.format(pickUpDate));
You can use the above code to get formatted Date as String
Use this Code:
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd");
Date pickUpDate =sdf.parse("2007-06-21");
System.out.println("pickUpDate "+sdf.format(pickUpDate));
Hope it'll help you.
String your_format_date=sdf.format(pickUpDate);
System.out.println("pick Up Date " + your_format_date);
Date isn't a date. It's a timestamp. That's some impressive API design, isn't it?
The type you need is now java.time.LocalDate, added in Java 8.
If you can't use Java 8, you can use ThreeTen, a backport for Java 7.

How to convert a String to a Date using SimpleDateFormat?

I have this code snippet:
DateFormat formatter1;
formatter1 = new SimpleDateFormat("mm/DD/yyyy");
System.out.println((Date)formatter1.parse("08/16/2011"));
When I run this, I get this as the output:
Sun Jan 16 00:10:00 IST 2011
I expected:
Tue Aug 16 "Whatever Time" IST 2011
I mean to say I am not getting the month as expected. What is the mistake?
Try this:
new SimpleDateFormat("MM/dd/yyyy")
MM is "month" (not mm)
dd is "day" (not DD)
It's all in the javadoc for SimpleDateFormat
FYI, the reason your format is still a valid date format is that:
mm is "minutes"
DD is "day in year"
Also, you don't need the cast to Date... it already is a Date (or it explodes):
public static void main(String[] args) throws ParseException {
System.out.println(new SimpleDateFormat("MM/dd/yyyy").parse("08/16/2011"));
}
Output:
Tue Aug 16 00:00:00 EST 2011
Voila!
m - min M - Months
Letter Date or Time Component Presentation Examples
G Era designator Text AD
y Year Year 1996; 96
M Month in year Month July; Jul; 07
w Week in year Number 27
W Week in month Number 2
D Day in year Number 189
d Day in month Number 10
F Day of week in month Number 2
E Day in week Text Tuesday; Tue
a Am/pm marker Text PM
H Hour in day (0-23) Number 0
k Hour in day (1-24) Number 24
K Hour in am/pm (0-11) Number 0
h Hour in am/pm (1-12) Number 12
m Minute in hour Number 30
s Second in minute Number 55
S Millisecond Number 978
z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
Z Time zone RFC 822 time zone -0800
Use the below function
/**
* Format a time from a given format to given target format
*
* #param inputFormat
* #param inputTimeStamp
* #param outputFormat
* #return
* #throws ParseException
*/
private static String TimeStampConverter(final String inputFormat,
String inputTimeStamp, final String outputFormat)
throws ParseException {
return new SimpleDateFormat(outputFormat).format(new SimpleDateFormat(
inputFormat).parse(inputTimeStamp));
}
Sample Usage is as Following:
try {
String inputTimeStamp = "08/16/2011";
final String inputFormat = "MM/dd/yyyy";
final String outputFormat = "EEE MMM dd HH:mm:ss z yyyy";
System.out.println(TimeStampConverter(inputFormat, inputTimeStamp,
outputFormat));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String newstr = "08/16/2011";
SimpleDateFormat format1 = new SimpleDateFormat("MM/dd/yyyy");
SimpleDateFormat format = new SimpleDateFormat("EE MMM dd hh:mm:ss z yyyy");
Calendar c = Calendar.getInstance();
c.setTime(format1.parse(newstr));
System.out.println(format.format(c.getTime()));
Very Simple Example is.
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
Date date = new Date();
Date date1 = new Date();
try {
System.out.println("Date1: "+date1);
System.out.println("date" + date);
date = simpleDateFormat.parse("01-01-2013");
date1 = simpleDateFormat.parse("06-15-2013");
System.out.println("Date1 is:"+date1);
System.out.println("date" + date);
} catch (Exception e) {
System.out.println(e.getMessage());
}
This piece of code helps to convert back and forth
System.out.println("Date: "+ String.valueOf(new Date()));
SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String stringdate = dt.format(new Date());
System.out.println("String.valueOf(date): "+stringdate);
try {
Date date = dt.parse(stringdate);
System.out.println("parse date: "+ String.valueOf(date));
} catch (ParseException e) {
e.printStackTrace();
}
you can solve the problem much simple like
First convert the the given string to the date object
eg:
java.util.Date date1 = new Date("11/19/2015");
SimpleDateFormat formatter = new SimpleDateFormat("MMM dd yyyy HH:mma");
String format = formatter.format(date);
System.out.println(format);
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/uuuu");
System.out.println(LocalDate.parse("08/16/2011", dateFormatter));
Output:
2011-08-16
I am contributing the modern answer. The answer by Bohemian is correct and was a good answer when it was written 6 years ago. Now the notoriously troublesome SimpleDateFormat class is long outdated and we have so much better in java.time, the modern Java date and time API. I warmly recommend you use this instead of the old date-time classes.
What went wrong in your code?
When I parse 08/16/2011 using your snippet, I get Sun Jan 16 00:08:00 CET 2011. Since lowercase mm is for minutes, I get 00:08:00 (8 minutes past midnight), and since uppercase DD is for day of year, I get 16 January.
In java.time too format pattern strings are case sensitive, and we needed to use uppercase MM for month and lowercase dd for day of month.
Question: Can I use java.time with my Java version?
Yes, java.time works nicely on Java 6 and later and on both older and newer Android devices.
In Java 8 and later and on new Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
String localFormat = android.text.format.DateFormat.getBestDateTimePattern(Locale.getDefault(), "EEEE MMMM d");
return new SimpleDateFormat(localFormat, Locale.getDefault()).format(localMidnight);
will return a format based on device's language.
Note that getBestDateTimePattern() returns "the best possible localized form of the given skeleton for the given locale"
You have used some type errors. If you want to set 08/16/2011 to following pattern. It is wrong because,
mm stands for minutes, use MM as it is for Months
DD is wrong, it should be dd which represents Days
Try this to achieve the output you want to get ( Tue Aug 16 "Whatever Time" IST 2011 ),
String date = "08/16/2011"; //input date as String
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy"); // date pattern
Date myDate = simpleDateFormat.parse(date); // returns date object
System.out.println(myDate); //outputs: Tue Aug 16 00:00:00 IST 2011

Categories

Resources