Robert
Robert

Reputation: 1638

Understanding JodaTime DateTime.parse(string, formatter)

Does the style of the formatter in the parse method of the DateTime class have to match the exact style of the string? For instance, I'm getting a TimeStamp object from the database (Oracle) and converting it to a string. In the database the TimeStamp is stored like this

08-AUG-12 12.00.00.000000000 AM

I set my formatter to this style

String pattern = "dd-MMM-yy";

I get this exception

java.lang.IllegalArgumentException: Invalid format: "08-AUG-12 12.00.00 AM" is malformed at " 12.00.00 AM"

org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:866)

org.joda.time.DateTime.parse(DateTime.java:144)

What exactly does this mean and how would I go about fixing it? When I set my formatter to "yy-MMM-dd hh.mm.ss aa" I don't get an exception but it prints in the browser like this: 2008-08-12T00:00:00.000-04:00, but I need for it to print out as "dd-MMM-yy hh:mm:ss aa"

Upvotes: 20

Views: 70049

Answers (3)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79075

java.time

In March 2014, Java 8 introduced the modern, java.time date-time API which supplanted the error-prone legacy java.util date-time API. Any new code should use the java.time API*.

Also, shown below is a notice on the Joda-Time Home Page:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Solution using modern date-time API

Does the style of the formatter in the parse method of the DateTime class have to match the exact style of the string?

Mostly 'Yes'. However, there are some exceptions e.g. a single u can parse a 4-digit year, a single M can parse one/two-digit month, a single d can parse one/two-digit day-of-month etc. e.g. LocalDate.parse("15/10/2024", DateTimeFormatter.ofPattern("d/M/u")). I recommend you go through DateTimeFormatter documentation to learn more about it.

In the database the TimeStamp is stored like this

08-AUG-12 12.00.00.000000000 AM

I suggest you build a case-insensitive DateTimeFormatter to deal with cases like AUG/Aug, AM/am etc. The demo below shows how to create such a DateTimeFormatter.

Also, use an appropriate Locale whenever the date-time string you are parsing has alphabets (e.g. AUG, AM etc.) as they are Locale-sensitive. You may like to check Always specify a Locale with a SimpleDateFormat, and a DateTimeFormatter for custom formats.

Demo:

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .appendPattern("dd-MMM-uu hh.mm.ss.SSSSSSSSS a")
                .toFormatter(Locale.ENGLISH);
        LocalDateTime ldt = LocalDateTime.parse("08-AUG-12 12.00.00.000000000 AM", dtf);
        System.out.println(ldt);
    }
}

Output:

2012-08-08T00:00

Online Demo

Note: As suggested by https://stackoverflow.com/users/5772882/anonymous, retrieving it as a LocalDateTime from your database is even better. Given below is a sample code:

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
    // Assuming the column index of columnfoo is 1
    LocalDateTime ldt = rs.getObject(1, LocalDateTime.class));
    System.out.println(ldt);
}
rs.close();
st.close();

Check this answer and this answer to learn more about this option.

Learn more about the modern Date-Time API from Trail: Date Time.

Upvotes: 0

Eugene
Eugene

Reputation: 120858

Use LocalDateTime instead:

String input = "08-AUG-12 12.00.00 AM";
String pattern = "dd-MMM-yy hh.mm.ss aa";

LocalDateTime localDateTime = LocalDateTime.parse(input, DateTimeFormat.forPattern(pattern));

EDIT

As a matter of fact you can do it with DateTime also:

private static String parseDateTime(String input){
     String pattern = "dd-MMM-yy hh.mm.ss aa";
     DateTime dateTime  = DateTime.parse(input, DateTimeFormat.forPattern(pattern));
     return dateTime.toString("dd-MMM-yy hh:mm:ss aa");
}

Upvotes: 54

Robert
Robert

Reputation: 1638

Figured it out. To get the correct format, you have to call formatter.print(localDateTime object) and it worked.

Upvotes: 2

Related Questions