Parse function unable to parse string and throwing error in Java - java

Not able to parse the following date. Getting parse exception. Please help in finding error :
String myDate = "2020–03–01 3:15 pm";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm aa",Locale.ENGLISH);
Date date = sdf.parse(myDate);

The separator character that you have used to separate the year, the month and the day doesn't seem to be correct. I suggest you type the date-time string again instead of copying and pasting it from somewhere. I also recommend you switch from the outdated date-time API to the modern one.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String myDate = "2020-03-01 3:15 pm";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("u-M-d h:m a")
.toFormatter(Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(myDate, formatter);
System.out.println(ldt);
}
}
Output:
2020-03-01T15:15
If you still want to use the legacy date-time API, you can do it as follows:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
String myDate = "2020-03-01 3:15 pm";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd h:mm aa", Locale.ENGLISH);
Date date = sdf.parse(myDate);
System.out.println(date);
}
}
Output:
Sun Mar 01 15:15:00 GMT 2020
Note that I've used a single h to match your date-time string.

From the looks of it your date string contains – (dash) instead of - (hyphen).
Try using hyphens in the date instead and see if it manages to parse it correctly.
Bonus ascii table details:
Dash (-):
.
Hyphen (-):

Related

How to convert a date with time zone offset to another format

I tried reading a lot about the date formatting with time zone, but it doesn't make sense to me.
My DB shows this datetime: 2022-12-01 04:00:00.000 +08:00
My UI shows it as: Thu 01/12/2022 12:00
I need to compare between them to verify they are the same. I tried to convert the DB time like this:
String dbDate = "2022-12-01 04:00:00.000 +08:00";
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS XXX");
Date date = sf.parse(dbDate)
sf = new SimpleDateFormat("EEE dd/MM/yyy HH:mm");
String uiDate = sf.format(date);
The results received is a completely different date: 'Wed 30/11/2022 22:02'.
I don't understand the logic here and would appreciate help in converting it correctly.
As already commented by Yonatan Karp-Rudin, you can not compare a date-time with time-zone offset with another without time-zone offset. A clear way to compare the two date-times is to bring them to a single time-zone e.g. you can apply the same time-zone offset to the UI date-time as of the DB date-time.
In March 2014, java.time API supplanted the error-prone legacy date-time API. Since then, it has been strongly recommended to use this modern date-time API.
Demo using java.time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dt1 = "2022-12-01 04:00:00.000 +08:00";
String dt2 = "Thu 01/12/2022 12:00";
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
OffsetDateTime odt1 = OffsetDateTime.parse(dt1, dtf1);
System.out.println(odt1);
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH)
.withZone(odt1.getOffset());
OffsetDateTime odt2 = OffsetDateTime.parse(dt2, dtf2);
System.out.println(odt2);
System.out.println(odt1.equals(odt2));
}
}
Output:
2022-12-01T04:00+08:00
2022-12-01T12:00+08:00
false
Assuming both the date-times belong to the same time-zone offset, another way to compare them would be compare them without time-zone i.e. comparing their date-time part only (LocalDateTime).
Demo:
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String dt1 = "2022-12-01 04:00:00.000 +08:00";
String dt2 = "Thu 01/12/2022 12:00";
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
LocalDateTime ldt1 = OffsetDateTime.parse(dt1, dtf1).toLocalDateTime();
System.out.println(ldt1);
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH);
LocalDateTime ldt2 = LocalDateTime.parse(dt2, dtf2);
System.out.println(ldt2);
System.out.println(ldt1.equals(ldt2));
}
}
Output:
2022-12-01T04:00
2022-12-01T12:00
false
The modern date-time API (java.time API) provides you with tools to do the same thing in many ways e.g. in the 1st demo, we could obtain the OffsetDateTime for your UI date-time string by parsing it into a LocalDateTime as shown in the 2nd demo and then using one of the ways shown in this answer where ZoneOffset offset = odt1.getOffset().
By the way, here is an example of how you format a date-time with time-zone offset to another format:
public class Main {
public static void main(String[] args) {
String dtDb = "2022-12-01 04:00:00.000 +08:00";
DateTimeFormatter parser = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSS XXX", Locale.ENGLISH);
OffsetDateTime odtDb = OffsetDateTime.parse(dtDb, parser);
System.out.println(odtDb);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE dd/MM/uuuu HH:mm", Locale.ENGLISH);
String strDtUi = odtDb.format(formatter);
System.out.println(strDtUi);
}
}
Output:
2022-12-01T04:00+08:00
Thu 01/12/2022 04:00
Learn more about the modern Date-Time API from Trail: Date Time.

How to convert time string into date and time format?

I having a hard time trying to format a string time into MM:DD::YY and only time. From an IP i getting the time in the following format
2021-09-10T00:37:42Z
and I'm want to display the date and time in:
09/08/2021
Time
09:50PM
Parse the given string into OffsetDateTime and then get LocalDate and LocalTime parts out of it.
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2021-09-10T00:37:42Z";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
LocalTime time = odt.toLocalTime();
LocalDate date = odt.toLocalDate();
System.out.println(time);
System.out.println(date);
// #########Custom formats #########
DateTimeFormatter dtfDate = DateTimeFormatter.ofPattern("MM/dd/uuuu", Locale.ENGLISH);
String formattedDateString = date.format(dtfDate);
System.out.println(formattedDateString);
DateTimeFormatter dtfTime = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);
String formattedTimeString = time.format(dtfTime);
System.out.println(formattedTimeString);
}
}
Output:
00:37:42
2021-09-10
09/10/2021
12:37 AM
ONLINE DEMO
Learn more about the modern Date-Time API* from Trail: Date Time.
Update based on an important comment by Ole V.V.:
The OP — or their user — may want the date and time in their own time
zone.
In order to get the date and time parts in a specific timezone e.g. America/Los_Angeles, you should parse the given date-time string into ZonedDateTime and convert the same to the ZonedDateTime of the specific timezone using ZonedDateTime#withZoneSameInstant. Rest of the things will remain same as the original answer.
Demo:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "2021-09-10T00:37:42Z";
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime);
ZonedDateTime zdtLosAngeles = zdt.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
LocalTime time = zdtLosAngeles.toLocalTime();
LocalDate date = zdtLosAngeles.toLocalDate();
System.out.println(time);
System.out.println(date);
// #########Custom formats #########
DateTimeFormatter dtfDate = DateTimeFormatter.ofPattern("MM/dd/uuuu", Locale.ENGLISH);
String formattedDateString = date.format(dtfDate);
System.out.println(formattedDateString);
DateTimeFormatter dtfTime = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);
String formattedTimeString = time.format(dtfTime);
System.out.println(formattedTimeString);
}
}
Output:
17:37:42
2021-09-09
09/09/2021
05:37 PM
ONLINE DEMO
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

How to convert String with no time into full date with time using DateTimeFormatter

Hi I am trying to convert a String into date using DateTimeFormatter,
such as "20210628" to "Mon Jun 28 00:00:00 UTC 2021".
It can be achieved easily using SimpleDateFormatter but I want to achieve it using DateTimeFormatter.
java.time
The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time, the modern Date-Time API:
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("uuuuMMdd", Locale.ENGLISH);
LocalDate date = LocalDate.parse("20210628", dtfInput);
OffsetDateTime odt = date.atTime(OffsetTime.of(LocalTime.MIN, ZoneOffset.UTC));
System.out.println(odt);
// Custom format
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O uuuu", Locale.ENGLISH);
System.out.println(dtfOutput.format(odt));
}
}
Output:
2021-06-28T00:00Z
Mon Jun 28 00:00:00 GMT 2021
ONLINE DEMO
Alternatively,
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("uuuuMMdd", Locale.ENGLISH);
LocalDate date = LocalDate.parse("20210628", dtfInput);
ZonedDateTime zdt = date.atStartOfDay(ZoneId.of("Etc/UTC"));
System.out.println(zdt);
// Custom format
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O uuuu", Locale.ENGLISH);
System.out.println(dtfOutput.format(zdt));
}
}
Output:
2021-06-28T00:00Z[Etc/UTC]
Mon Jun 28 00:00:00 GMT 2021
ONLINE DEMO
Learn more about the modern Date-Time API from Trail: Date Time.
A different approach using java.time, too...
Use a DateTimeFormatterBuilder to get full control over String conversion.
Here's a small example that really prints UTC instead of GMT or Z in the desired output:
public static void main(String[] args) {
// example String
String value = "20210628";
// define a formatter that parses the example String
DateTimeFormatter dateParser = DateTimeFormatter.ofPattern("uuuuMMdd");
// define a formatter that converts to a String as desired
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss")
.appendLiteral(' ')
.appendZoneRegionId()
.appendLiteral(' ')
.appendPattern("uuuu")
.toFormatter(Locale.ENGLISH);
// parse the date and use the formatter in order to get the desired result
String otherValue = LocalDate.parse(value, dateParser)
// add the start of the day
.atStartOfDay()
// apply the desired zone
.atZone(ZoneId.of("UTC"))
// and format it
.format(dtf);
// finally print the conversion
System.out.println(value + " ---> " + otherValue);
}
The output will be as follows:
20210628 ---> Mon Jun 28 00:00:00 UTC 2021
If you already have a LocalDateTime object then you can use the following.
String getFormattedDate(LocalDateTime datetime){
DateTimeFormatter formatterPreUTC = DateTimeFormatter.ofPattern("E MMM dd HH:mm:ss");
DateTimeFormatter formatterPostUTC = DateTimeFormatter.ofPattern("YYYY");
String textPreUTCPart = datetime.format(formatterPreUTC);
String utc = " UTC ";
String textPostUTCPart = datetime.format(formatterPostUTC);
return textPreUTCPart + utc + textPostUTCPart;
}

How to get Date object from MONTH("MMMM") or YEAR("yyyy") using DateTimeFormatter

I am new to using DateTimeFormatter package, and same thing we are able to get using SimpleDateFormat.
Date date = new SimpleDateFormat("MMMM").parse(month);//"DECEMBER"
Date date = new SimpleDateFormat("yyyy").parse(year);//"2020"
How to achive this using DateTimeFormatter?
DateTimeFormatter not supporting with util.Date class, here you need to use LocalDate class. You can't parse only with month or year, you should pass 3 values of month, day and year to get Date.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate parsedDate = LocalDate.parse("2020 12 15", formatter);
System.out.print(parsedDate); //2020-12-15
String monthString = "December";
DateTimeFormatter monthFormatter
= DateTimeFormatter.ofPattern("MMMM", Locale.ENGLISH);
Month month = monthFormatter.parse(monthString, Month::from);
System.out.println(month);
Output:
DECEMBER
Year is somewhat simpler. We don’t need a formatter.
String yearString = "2020";
Year year = Year.parse(yearString);
System.out.println(year);
2020
The old Date class despite its name never represented a date. It was a point in time. Yet we commonly used it for a date, a time of day, a month, a year and still more purposes, sometimes also for the point in time that it was. One very confusing consequence was that the Date objects obtained from the code in your question would under rare circumstances incorrectly print as November instead of December and as 2019 instead of 2020. You should no longer use the Date class. It was always poorly designed and is long outdated.
On the other hand java.time, the modern Java date and time API to which DateTimeFormatter belongs, defines a class for each such concept: LocalDate for a date, Month for a month of year, Year for a year, etc. It makes our code clearer about what we are dealing with, which is good. It also requires us to learn about the different classes and think about which one to use each time.
If your month string was in all uppercase, we need to tell the formatter to parse without regard to case:
String monthString = "DECEMBER";
DateTimeFormatter monthFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("MMMM")
.toFormatter(Locale.ENGLISH);
Month month = monthFormatter.parse(monthString, Month::from);
Also when your month name is in English remember to specify an English-speaking locale.
check this link https://www.baeldung.com/java-datetimeformatter.
you can use custom format as
String europeanDatePattern = "dd.MM.yyyy";
DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern);
System.out.println(europeanDateFormatter.format(LocalDate.of(2016, 7, 31)))
The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. Let's see them in action:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Main {
public static void main(String[] args) throws ParseException {
Date date1 = new SimpleDateFormat("MMMM").parse("DECEMBER");
System.out.println(date1);
Date date2 = new SimpleDateFormat("yyyy").parse("2020");
System.out.println(date2);
}
}
Output:
Tue Dec 01 00:00:00 GMT 1970
Wed Jan 01 00:00:00 GMT 2020
I do not need to explain what defaults they are taking. Instead of taking such unexpected defaults, they should have raised an alarm (throw some exception) which would have become helpful to a programmer to react to.
Because of such surprises, it is recommended to stop using them completely and switch to the modern date-time API.
Note: For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7.
If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Using the modern date-time API:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class Main {
public static void main(String[] args) {
System.out.println(parse("DECEMBER", "MMMM"));
System.out.println(parse("2020", "uuuu"));
}
static LocalDate parse(String text, String pattern) {
try {
return LocalDate.parse(text, DateTimeFormatter.ofPattern(pattern));
} catch (DateTimeParseException e) {
System.out.println(e.getMessage());
// Return some default value
return LocalDate.MIN;
}
}
}
Output:
Text 'DECEMBER' could not be parsed at index 0
-999999999-01-01
Text '2020' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {Year=2020},ISO of type java.time.format.Parsed
-999999999-01-01
So, now you (the programmer) get to know that you have to do something (e.g. use your own defaults) to parse the strings.
Demo:
import java.time.LocalDate;
import java.time.Month;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
LocalDate date = parse("DECEMBER", "MMMM");
Month month = parse("DECEMBER", "MMMM").getMonth();
System.out.println(date);
System.out.println(month);
date = parse("2020", "uuuu");
System.out.println(date);
int year = date.getYear();
System.out.println(year);
Year objYear = Year.of(year);
System.out.println(objYear);
}
static LocalDate parse(String text, String pattern) {
LocalDate today = LocalDate.now();
// Formatter using today's day, month and year as defaults
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern(pattern)
.parseDefaulting(ChronoField.DAY_OF_MONTH, today.getDayOfMonth())
.parseDefaulting(ChronoField.MONTH_OF_YEAR, today.getMonthValue())
.parseDefaulting(ChronoField.YEAR, today.getYear())
.toFormatter(Locale.ENGLISH);
try {
return LocalDate.parse(text, formatter);
} catch (DateTimeParseException e) {
System.out.println(e.getMessage());
// Return some default value
return LocalDate.MIN;
}
}
}
Output:
2020-12-15
DECEMBER
2020-12-15
2020
2020
If you do not want to create a date or date-time object, rather, if all you want to do is to parse your string into Month and Year, you can do it simply the following way:
import java.time.Month;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.TextStyle;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
Month month = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("MMMM")
.toFormatter(Locale.ENGLISH)
.parse("DECEMBER", Month::from);
System.out.println(month + " | " + month.getDisplayName(TextStyle.SHORT, Locale.ENGLISH) + " | "
+ month.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
Year year = DateTimeFormatter.ofPattern("uuuu").parse("2020", Year::from);
System.out.println(year);
}
}
Output:
DECEMBER | Dec | December
2020
Learn more about the modern date-time API at Trail: Date Time.

Get formatted string from Calendar

I've got a Calendar Date in Java.
I need to convert it in a String with this format :
2020-12-29T00:00:00+01:00
How can I do it?
Thank you so much for your help.
Get the Date object by calling Calendar#getTime and format it using a SimpleDateFormat with the format, yyyy-MM-dd'T'HH:mm:ssXXX.
Note: Since the desired string has timezone offset of +01:00 hours, make sure you set the timezone of the SimpleDateFormat object to TimeZone.getTimeZone("GMT+1") before calling SimpleDateFormat#format.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
Date date = calendar.getTime();
String formatted = sdf.format(date);
System.out.println(formatted);
}
}
Another example:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String dateTimeString = "2020-12-29T00:00:00+01:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Date obj = sdf.parse(dateTimeString);
Calendar calendar = Calendar.getInstance();
calendar.setTime(obj);
// Formatting this calendar object
Date date = calendar.getTime();
sdf.setTimeZone(TimeZone.getTimeZone("GMT+1"));
String formatted = sdf.format(date);
System.out.println(formatted);
}
}
Output:
2020-12-29T00:00:00+01:00
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work.
Here’s a formatter for your desired format:
private static final DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssXXX");
With this we may do:
ZoneId zone = ZoneId.of("Asia/Barnaul");
ZonedDateTime dateTime
= LocalDate.of(2020, Month.DECEMBER, 29).atStartOfDay(zone);
String formatted = dateTime.format(formatter);
System.out.println(formatted);
Output from this example snipoet is:
2020-12-29T00:00:00+07:00
If you cannot avoid getting a Calendar
If you are getting a Calendar object from a legacy API that you cannot afford to upgrade to java.time just now, convert it to ZonedDateTime. It is almost certainly really a GregorianCalendar (or formatting into that format would not make much sense), which makes the conversion straightforward.
Calendar yourCalendar = getCalendarFromLegacyApi();
ZonedDateTime dateTime
= ((GregorianCalendar) yourCalendar).toZonedDateTime();
The rest is as before, as is the output.
If you need to take into account the possibility that the Calendar is not a GregorianCalendar, use this slightly more complicated conversion instead:
ZonedDateTime dateTime = yourCalendar.toInstant()
.atZone(yourCalendar.getTimeZone().toZoneId());
Link
Oracle tutorial: Date Time explaining how to use java.time.

Categories