Date Format Parse Exception - "Eee Mmm Dd Hh:Mm:Ss Z Yyyy"

Date parse exception EEE MMM dd HH:mm:ss z yyyy in few cases

java.time

I recommend that you use java.time, the modern Java date and time API, for your date and time work. Parsing all four of your strings is a bit of challenge alright. The following formatter works.

// Substitute your own set of preferred zones here
private static final Set<ZoneId> PREFERRED_ZONES
= Set.of(ZoneId.of("Atlantic/Reykjavik"), ZoneId.of("America/Havana"));
private static final DateTimeFormatter PARSER = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd HH:mm:ss [O][")
.appendZoneText(TextStyle.SHORT, PREFERRED_ZONES)
.appendPattern("] yyyy")
.toFormatter(Locale.ENGLISH);

Trying it out:

    String[] strings = {
"Mon Jul 12 13:42:07 GMT+1 2021",
"Sat Jul 17 09:20:27 IST 2021",
"Sun Oct 11 12:56:41 GMT+05:30 2020",
"Fri Aug 20 03:33:16 CST 2021"
};

for (String string : strings) {
ZonedDateTime zdt = ZonedDateTime.parse(string, PARSER);
System.out.println(zdt);
}

Output is:

2021-07-12T13:42:07+01:00
2021-07-17T09:20:27Z[Atlantic/Reykjavik]
2020-10-11T12:56:41+05:30
2021-08-20T03:33:16-04:00[America/Havana]

While IST, GMT+05:30 and CST can be parsed as time zone abbreviations, GMT+1 cannot. So I am instructing my formatter to parse a localized offset if it can. Pattern letter O parses GMT+1 in English (and most other locales). And then to try to parse a time zone abbreviation. The square brackets in the format pattern strings denote optional parts.

Next challenge was that IST and CST like many time zone abbreviations are ambiguous. So I am also giving the formatter a set of preferred time zones to use to solve the ambiguities. You need to decide which time zones you want those abbreviations to denote, and supply a corresponding set of ZonedId objects.

Format parse exception “EEE MMM dd HH:mm:ss Z yyyy”

Since the error message is complaining about offset 20, which is the BRST value, it seems that it cannot resolve the time zone.

Please try this code, that should ensure that the Brazilian time zone is recognized:

SimpleDateFormat sdf = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("America/Sao_Paulo"));
System.out.println(sdf.parse("Wed Oct 19 14:34:26 BRST 2016"));

Since I'm in Eastern US, that prints this for me:

Wed Oct 19 12:34:26 EDT 2016

Date format parse exception - EEE MMM dd HH:mm:ss Z yyyy

I'm going to assume that Locale.getDefault() for you is pl-PL since you seem to be in Poland.

English words in date strings therefore cause an unparseable date.

An appropriate Polish date String would be something like

"Wt paź 16 00:00:00 -0500 2013"

Otherwise, change your Locale to Locale.ENGLISH so that the SimpleDateFormat object can parse String dates with English words.

How to compare the datetime of format EEE MMM dd HH:mm:ss zzz yyyy and yyyy-MM-dd hh:mm:sss in java?

If you assume that the timezone of the second date is the same as for the first one then you can just use java.time. It has all parsing tools you need. Any other fixed timezone works as well.

Here is an example:

String a = "Wed Mar 04 03:34:45 GMT+08:00 2020";
String b = "2020-02-04 02:10:58";

ZonedDateTime parsedA;
ZonedDateTime parsedB;

DateTimeFormatter formatterA = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy");
parsedA = ZonedDateTime.parse(a, formatterA);
DateTimeFormatter formatterB = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
parsedB = LocalDateTime.parse(b, formatterB).atZone(parsedA.getZone());

// What do you want to compare? For example you can tell if a is after b.
System.out.println(parsedA.isAfter(parsedB));

Have a look here if you need another format and need a listing of Pattern Letters and Symbols.

Talend - Transform EEE MMM dd hh:mm:ss z yyyy in yyyy-MM-dd

You could achieve the format using the below code snippet -

System.out.println(input_row.newColumn);
SimpleDateFormat parserSDF = new SimpleDateFormat("EEE MMM dd hh:mm:ss z yyyy", Locale.ENGLISH);
Date date = parserSDF.parse(input_row.newColumn);
String dDate = null;
parserSDF = new SimpleDateFormat("yyyy-MM-dd");
dDate = parserSDF.format(date);
System.out.println(dDate);

Also, you need the below libraries to be imported(Advanced settings section of tJavaRow)-

import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Date;

I had directly passed the input value from file(in my scenario tFileInputDelimited) into tJavaRow as - input_row.newColumn and then used SimpleDateFormat class to both parse and format dates according to the formatting pattern.

Read more here.

Not able to parse String date of format IST and GMT format

I was looking for answer why its not able to parce String Sun Dec 06 11:15:00 IST 2015 using SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy") other date formats like String date 01 10 2018 this with dd MM YYYY format able to parce but not above. So

I have tried this alternative way to get respective date format.

Hope this will help some one

value is date object

Date date   = d.parse(value);
Calendar c = Calendar.getInstance();
c.setTime(date);
int dd = c.get(Calendar.DAY_OF_MONTH);
int mmm = c.get(Calendar.MONTH) + 1;
int yyyy = c.get(Calendar.YEAR);

String dateString = "" + dd + "-" + mmm + "-" + yyyy;

Convert date fomat EEE MMM dd HH:mm:ss zzzz yyyy to yyyy-MM-dd'T'HH:mm:ss in Java

Edit: The comments by Jon Skeet and finally yourself give the answer: The first time you parse a string, the time zone database and the locale data included with the JVM need to be loaded in order to parse CET (or other time zone abbreviation in the string). This takes time. The next times theses data are already loaded, so parsing is fast.

You can improve the parsing time of the first string if on program startup you have time to do some time zone operation so the data are loaded. You may try ZoneId.systemDefault() or ZoneId.systemDefault().getDisplayName(TextStyle.SHORT, Locale.ENGLISH) or simply parsing a (hardcoded) string like the ones in the database.

Original answer: Change the database schema to store the date and time as timestamp with time zone or datetime. This will save you from parsing. (If there’s data in your table already, converting it will take time, of course, but that’s only once and doesn’t happen while the user is waiting for a response.)

If you can’t change the database schema, here’s a more direct answer to your question. It’s ugly code because it’s written for optimization, so only use it as a last resort.

private static DateTimeFormatter monthFormatter
= DateTimeFormatter.ofPattern("MMM", Locale.ROOT);

int m = Month.from(monthFormatter.parse(value.subSequence(4, 7))).getValue();
if (m < 10) {
return value.substring(value.length() - 4) + "-0" + m + '-' + value.substring(8, 10) + 'T' + value.substring(11, 19);
} else {
return value.substring(value.length() - 4) + '-' + m + '-' + value.substring(8, 10) + 'T' + value.substring(11, 19);
}

On my 10 years old computer this reduced the time from 1.78 milliseconds to 0.73 ms per conversion, measured with System.nanoTime() on 100 conversions. A 59 % reduction compared to your code.

You may be able to get a further reduction if you make your own HashMap lookup of the month abbreviation instead of using a DateTimeFormatter.

How to convert Java String EEE MMM dd HH:mm:ss zzz yyyydate type to Java util.Date yyyy-MM-dd

tl;dr

ZonedDateTime
.parse(
"Sat Dec 12 00:00:00 KST 2020" ,
DateTimeFormatter
.ofPattern( "EEE MMM dd HH:mm:ss zzz uuuu" )
.withLocale( Locale.US )
)
.toLocalDate()
.toString()

2020-12-12

Avoid legacy date-time classes

You are using terrible date-time classes that were supplanted years ago by the modern java.time classes. Never use Date, Calendar, or SimpleDateFormat.

You said:

my target date type is Java Date type with format yyyy-MM-dd.

Apparently, you expect Date to hold a date. It does not. The java.util.Date class represents a moment, a date with time-of-day as seen in UTC. The java.sql.Date class pretends to hold only a date, but it too actually contains a date with time-of-day as seen in UTC.

Among the many problems with java.util.Date class is the behavior of its toString method. That method dynamically applies the JVM’s current default time zone while generating text. This anti-feature may contribute to your confusion.

LocalDate

Instead you should be using java.time.LocalDate to represent a date-only value without a time-of-day and without a time zone or offset-from-UTC.

ZonedDateTime

First use the DateTimeFormatter class to parse your entire input string. This results in a ZonedDateTime object representing a moment as seen through the wall-clock time used by the people of a particular region.

Example code

String input = "Sat Dec 12 00:00:00 KST 2020" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM dd HH:mm:ss zzz uuuu" ).withLocale( Locale.US ) ;
ZonedDateTime zdt = ZonedDateTime.parse( input , f ) ;

From that ZonedDateTime object, extract a LocalDate.

LocalDate localDate = zdt.toLocalDate() ;

See this code run live at IdeOne.com.

zdt.toString(): 2020-12-12T00:00+09:00[Asia/Seoul]

ld.toString(): 2020-12-12



About java.time

Table of all date-time types in Java, both modern and legacy

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
    • Java 9 brought some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android (26+) bundle implementations of the java.time classes.
    • For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
      • If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….


Related Topics



Leave a reply



Submit