juell
juell

Reputation: 4960

Print from joda-time DateTimeFormatter with optional Parser

In a project using joda-time 2.1, I have the following DateTimeFormatter:

   /**
   * Parser for the "fraction" part of a date-time value.
   */
  private static final DateTimeParser FRACTION_PARSER =
      new DateTimeFormatterBuilder()
          .appendLiteral('.')
          .appendFractionOfSecond(3, 9)
          .toParser();

  /**
   * A formatter for a "local" date/time without time zone offset
   * (in the format "yyyy-dd-mmThh:mm:ss[.fff]").
   */
  private static final DateTimeFormatter FORMAT_LOCAL =
      new DateTimeFormatterBuilder()
          .append(ISODateTimeFormat.date())
          .appendLiteral('T')
          .append(ISODateTimeFormat.hourMinuteSecond())
          .appendOptional(FRACTION_PARSER)
          .toFormatter()
          .withZone(DateTimeZone.UTC);

It does exactly what I want. It parses dates with or without fractions, and prints them without fractions.

If I upgrade to a more recent version of joda-time, I get

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.UnsupportedOperationException: Printing is not supported
    at org.joda.time.format.DateTimeFormatterBuilder.toPrinter(DateTimeFormatterBuilder.java:136)

So I guess what I had before was an error, but it did exactly what I wanted to do! How do I get the same behavior, without making an error? I've tried using append(DateTimePrinter, DateTimeParser[]) with a null printer and with a printer that doesn't actually print anything and neither of them work.

Upvotes: 4

Views: 3603

Answers (2)

juell
juell

Reputation: 4960

So I eventually figured this out, the solution is to construct the complete parser and printer separately, like so:

  /**
   * Parser for the "fraction" part of a date-time value.
   */
  private static final DateTimeParser FRACTION_PARSER =
      new DateTimeFormatterBuilder()
          .appendLiteral('.')
          .appendFractionOfSecond(3, 9)
          .toParser();

  private static final DateTimeParser BASE_PARSER =
      new DateTimeFormatterBuilder()
          .append(ISODateTimeFormat.date())
          .appendLiteral('T')
          .append(ISODateTimeFormat.hourMinuteSecond())
          .appendOptional(FRACTION_PARSER)
          .toParser();

  private static final DateTimePrinter BASE_PRINTER =
      new DateTimeFormatterBuilder()
          .append(ISODateTimeFormat.date())
          .appendLiteral('T')
          .append(ISODateTimeFormat.hourMinuteSecond())
          // omit fraction of second
          .toPrinter();

  /**
   * A formatter for a "local" date/time without time zone offset
   * (in the format "yyyy-dd-mmThh:mm:ss[.fff]").
   */
  private static final DateTimeFormatter FORMAT_LOCAL =
      new DateTimeFormatterBuilder()
          .append(BASE_PRINTER, BASE_PARSER)
          .toFormatter()
          .withZone(DateTimeZone.UTC);

Upvotes: 5

Greg King
Greg King

Reputation: 140

Is there a reason you need to use the printer. Would this work for you? It compiles and outputs the correct date/time for me.

private static final DateTimeParser FRACTION_PARSER =
        new DateTimeFormatterBuilder()
                .appendLiteral('[')
                .appendLiteral('.')
                .appendFractionOfSecond(3, 9)
                .appendLiteral(']')
                .toParser();

/**
 * A formatter for a "local" date/time without time zone offset
 * (in the format "yyyy-dd-mmThh:mm:ss[.fff]").
 */
private static final DateTimeFormatter FORMAT_LOCAL =
        new DateTimeFormatterBuilder()
                .append(ISODateTimeFormat.date())
                .appendLiteral('T')
                .append(ISODateTimeFormat.hourMinuteSecond())

                .appendOptional(FRACTION_PARSER)
                        .toFormatter()
                        .withZone(DateTimeZone.UTC);

String strInputDateTime = "1990-12-11T13:12:22[.025]";

DateTime dt = FORMAT_LOCAL.parseDateTime(strInputDateTime);

System.out.println(dt);

From reading the Javdoc there is a mention of toParser(); not being used and instead to use toFormatter(); I hope this helps.

toParser

public DateTimeParser toParser() Internal method to create a DateTimeParser instance using all the appended elements. Most applications will not use this method. If you want a parser in an application, call toFormatter() and just use the parsing API.

Subsequent changes to this builder do not affect the returned parser.

Throws: UnsupportedOperationException - if parsing is not supported

http://www.joda.org/joda-time/apidocs/index.html

This might be more usefull actually

public DateTimeFormatter toFormatter() Constructs a DateTimeFormatter using all the appended elements. This is the main method used by applications at the end of the build process to create a usable formatter.

Subsequent changes to this builder do not affect the returned formatter.

The returned formatter may not support both printing and parsing. The methods DateTimeFormatter.isPrinter() and DateTimeFormatter.isParser() will help you determine the state of the formatter.

Throws: UnsupportedOperationException - if neither printing nor parsing is supported

Upvotes: 1

Related Questions