Using Joda Date & Time API to parse multiple formats

31,916

Solution 1

You can create multiple parsers and add them to the builder by using DateTimeFormatterBuilder.append method:

DateTimeParser[] parsers = { 
        DateTimeFormat.forPattern( "yyyy-MM-dd HH" ).getParser(),
        DateTimeFormat.forPattern( "yyyy-MM-dd" ).getParser() };
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append( null, parsers ).toFormatter();

DateTime date1 = formatter.parseDateTime( "2010-01-01" );
DateTime date2 = formatter.parseDateTime( "2010-01-01 01" );

Solution 2

Joda-Time supports this by allowing multiple parsers to be specified - DateTimeFormatterBuilder#append

Simply create your two formatters using a builder and call toParser() on each. Then use the builder to combine them using append.

Solution 3

Unfortunately I don't believe Joda Time has any such capabilities. It would be nice to have a "tryParseDateTime" method, but it doesn't exist.

I suggest you isolate this behaviour into your own class (one which takes a list of patterns, and will try each in turn) so that the ugliness is only in one place. If this is causing performance issues, you might want to try to use some heuristics to guess which format to try first. For example, in your case if the string starts with a digit then it's probably the first pattern.

Note that DateTimeFormatters in Joda Time are conventionally immutable - you shouldn't be creating a new one each time you want to parse a line. Create them once and reuse them.

Share:
31,916

Related videos on Youtube

Steve McLeod
Author by

Steve McLeod

Java is my thing. I run Barbary Software, a tiny software company in Barcelona, Spain. Our products are Feature Upvote, a SaaS tool for feature request tracking, and Saber Feedback, a feedback widget for any website.

Updated on July 05, 2022

Comments

  • Steve McLeod
    Steve McLeod almost 2 years

    I'm parsing third party log files containing date/time using Joda. The date/time is in one of two different formats, depending on the age of the log files I'm parsing.

    Currently I have code like this:

    try {
        return DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss").parseDateTime(datePart);
    } catch (IllegalArgumentException e) {
        return DateTimeFormat.forPattern("E, MMM dd, yyyy HH:mm").parseDateTime(datePart);
    }
    

    This works but contravenes Joshua Bloch's advice from Effective Java 2nd Edition (Item 57: Use exceptions only for exceptional conditions). It also makes it hard to determine if an IllegalArgumentException occurs due to a screwed up date/time in a log file.

    Can you suggest a nicer approach that doesn't misuse exceptions?

    • sly7_7
      sly7_7 almost 14 years
      Perhaps by guessing the pattern before using it.
  • sly7_7
    sly7_7 almost 14 years
    This answer gives a sense to my comment. I'm pretty satisfied :) I'm still a beginner, so I would not give it as answer
  • Steve McLeod
    Steve McLeod almost 14 years
    Thanks Jon. I knew about DateTimeFormatters being immutable, but for the sake of brevity in my code example created them explicitly. There are no intolerable performance issues, so I think I'll do what you suggest and create a class to hide the ugliness.
  • Steve McLeod
    Steve McLeod almost 14 years
    Whoa! Answered directly from the man himself! Love your work Stephen.
  • Steve McLeod
    Steve McLeod almost 14 years
    Hmm, I tried this, but Joda-Time then seems to expect the string being parsed to match a pattern that consists of BOTH the patterns appended together, rather than one OR the other.
  • JodaStephen
    JodaStephen almost 14 years
    Perhaps the forum is a better location to see if this is a bug - sourceforge.net/projects/joda-time/forums/forum/337835
  • Steve McLeod
    Steve McLeod over 13 years
    This works perfectly. I guess JodaStephen meant this to, but when I tried to do things according to his instructions the parsing failed.
  • Steven
    Steven about 10 years
    This does not work for for example '5-5-5' and '5-5-2005' if you want both dd-MM-yy and dd-MM-yyyy (could not parse exception). Later I found out that dd-MM-yy also parses dd-MM-yyyy just fine, so that resolved my problem.
  • shmosel
    shmosel about 6 years
    Strangely, despite the variety of append overloads, this is the only one that doesn't throw an exception when given conflicting formats.
  • granadaCoder
    granadaCoder over 5 years
    Boo Java for lack of TryParse functions like DotNet. The lack of tryParse routines and generic type erasure are my two biggest gripes. docs.oracle.com/javase/tutorial/java/generics/erasure.html