Pelicer
Pelicer

Reputation: 1584

Parsing from String to Date throws Unparsable Date Error

I have an variable called data, and it has today's date as in this format: Thu May 24 13:14:41 BRT 2018. Then I format it to MySQL's Date type format, which is yyyy-MM-dd. This code does it:

String dataFormatada = new SimpleDateFormat("yyyy-MM-dd").format(data);

What I want to do is to bring it back to Date type. I've tried somethings but they didn't work. The main solution is to do as discribed in this other Stack Overflow's questioin, and with a little mod I got to what's suposely what I want:

String target = "Thu Sep 28 20:29:30 JST 2000";
DateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date result =  df.parse(target);  
System.out.println(result);

But it doesn't work as I get this error when trying to parse:

java.text.ParseException: Unparseable date: "Thu Sep 28 20:29:30 JST 2000"

So I cannot just reformat the data variable, and I cannot bring dataFormatada back to Date format. How do I bring dataFormatada to Date type formatted as yyyy-MM-dd?

Upvotes: 0

Views: 1509

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 340118

tl;dr

For a SQL-standard DATE column, use the java.time.LocalDate class with JDBC 4.2 or later.

myPreparedStatement.setObject(
    … ,
    ZonedDateTime.parse(  // Represent a moment in a particular time zone.
        "Thu May 24 13:14:41 BRT 2018".replace( "BRT" , "Europe/London" ) ,
        DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" , Locale.UK )
    )
    .toLocalDate()        // Extract a date-only value, without time-of-day and without time zone.
)

ISO 8601

I have an variable called data, and it has today's date as in this format: Thu May 24 13:14:41 BRT 201

This is a terrible format. When exchanging date-time values as text, use only the standard ISO 8601 formats. Conveniently, the java.time classes use these formats by default when parsing/generating strings.

BST = ?? (Brazil Standard Time, British Standard Time, … )

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as BST or IST as they are not true time zones, not standardized, and not even unique(!).

The ZonedDateTime class will try to guess the intended time zone. But you should not be relying on guesses in your code.

String input = "Thu May 24 13:14:41 BRT 2018";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" , Locale.UK );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );

2018-05-24T13:14:41-03:00[America/Sao_Paulo]

Looks like java.time guessed you meant Brazil Standard Time by BST. If you meant some other zone such as British time, replace that BST string by a proper time zone name.

Specify Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.

String input = "Thu May 24 13:14:41 BRT 2018".replace( "BRT" , "Europe/London" );
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM d HH:mm:ss z uuuu" , Locale.UK );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );

2018-05-24T13:14:41+01:00[Europe/London]

LocalDate

You apparently care about only the date. So extract a date-only object, a LocalDate.

LocalDate ld = zdt.toLocalDate() ;

Smart objects, not dumb strings

Do not exchange date-time values with your database as text. Instead use JDBC and objects. As of JDBC 4.2 and later, you can directly exchange java.time objects with your database.

myPreparedStatement.setObject( … , ld ) ;

Retrieval.

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

About java.time

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.

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

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

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.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 1

Amit Bera
Amit Bera

Reputation: 7235

Your target String format is in EEE MMM dd HH:mm:ss zzz yyyy format. So you need to use EEE MMM dd HH:mm:ss zzz yyyy as pattern instead of yyyy-MM-dd.

    String target = "Thu Sep 28 20:29:30 JST 2000";
    DateFormat df = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ENGLISH);
    Date result =  df.parse(target);  
    System.out.println(result);

And if you want convert Date object i.e result to yyyy-MM-dd then please use the below code.

    DateFormat dfDateToStr = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
    String formattedDate  = dfDateToStr.format(result);
    System.out.println("Formatted Date String : "+formattedDate);

Upvotes: 2

xingbin
xingbin

Reputation: 28289

You need two formator, one to parse the orginal string to Date object, one to format it to desired string:

public static void main(String[] args) throws Exception {
    String target = "Thu Sep 28 20:29:30 JST 2000";
    DateFormat parser = new SimpleDateFormat("EEE MMM dd kk:mm:ss z yyyy", Locale.ENGLISH);
    Date result = parser.parse(target);
    System.out.println(result);

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    String dataFormatada = format.format(result);
}

Upvotes: 2

Related Questions