Package org.openmhealth.reference.util

Source Code of org.openmhealth.reference.util.ISOW3CDateTimeFormat$ISOW3CDateTimeParser

/*******************************************************************************
* Copyright 2013 Open mHealth
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/*
*  Copyright 2012 John Jenkins
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package org.openmhealth.reference.util;

import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import org.joda.time.format.DateTimeParserBucket;
import org.joda.time.format.ISODateTimeFormat;

/**
* <p>
* Factory that creates instances of DateTimeFormatter for the W3C's profile of
* the ISO 8601 standard.
* </p>
*
* <p>
* ISO8601 is the international standard for data interchange and defines many
* formats for representing date and time information. W3C has created a
* shorter, more specific list of formats.
* </p>
*
* <p>
* One major difference between this and the ISODateTimeFormatter is that this
* will always parse non-zone'd values, e.g. year, year-month, and
* year-month-day, with a default zone of UTC as opposed to the
* ISODateTimeFormatter which will give them JodaTime's configured default time
* zone.
* </p>
*
* @author John Jenkins
*/
public class ISOW3CDateTimeFormat {
  /**
   * <p>
   * A DateTimeParser that implements the W3C profile of the ISO 8601
   * representation of dates and times
   * (<a href="http://www.w3.org/TR/NOTE-datetime">
   * http://www.w3.org/TR/NOTE-datetime
   * </a>).
   * </p>
   *
   * <p>
   * The most common use-case of this library is through the
   * ISOW3CDateTimeFormat, which will create an instance of this parser.
   *
   * <pre>ISOW3CDateTimeFormat.dateTime();</pre>
   *
   * For date-only formats, the zone is set to UTC. Like all DateTimeParsers,
   * the zone information is overridden with JodaTime's default zone. If you
   * are creating this parser yourself and would like to preserve the zone,
   * be sure to call 'withOffsetParsed()' on the resulting parser.
   *
   * <pre>(new ISOW3CDateTimeParser()).withOffsetParsed();</pre>
   *
   * </p>
   *
   * @author John Jenkins
   */
  public static class ISOW3CDateTimeParser implements DateTimeParser {
    /**
     * The date-time formatter for the W3C's specifications for date-only
     * values.
     */
    private static final DateTimeParser ISO_W3C_DATE_PARSER;
    static {
      // The W3C defines 3 formats as valid ISO date values.
      DateTimeParser[] parsers = new DateTimeParser[3];
     
      // Just the year.
      parsers[0] = ISOW3CDateTimeFormat.year().getParser();
     
      // The year and month.
      parsers[1] = ISOW3CDateTimeFormat.yearMonth().getParser();
     
      // The year, month, and day.
      parsers[2] =
        ISOW3CDateTimeFormat.yearMonthDay().getParser();
     
      // Build the parser with the 3 sub-parsers.
      DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
      builder.append(null, parsers);
      ISO_W3C_DATE_PARSER = builder.toParser();
    }
   
    /**
     * The date-time formatter for the W3C's specifications for date-time
     * values.
     */
    private static final DateTimeParser ISO_W3C_DATE_TIME_PARSER;
    static {
      // The W3C defines 3 formats as valid ISO date-time values.
      DateTimeParser[] parsers = new DateTimeParser[3];
     
      // The year, month, day, hour, minute, and time zone.
      // Build the parser from the existing ISODateTimeParser for the
      // year, month, day, hour, and minute and add the time zone.
      parsers[0] = ISOW3CDateTimeFormat.dateHourMinuteZone().getParser();
     
      // The year, month, day, hour, minute, second, and time zone.
      parsers[1] =
        ISOW3CDateTimeFormat.dateHourMinuteSecondZone().getParser();
     
      // The year, month, day, hour, minute, and time zone.
      // Build the parser from the existing ISODateTimeParser for the
      // year, month, day, hour, and minute and add the time zone.
      parsers[2] = ISOW3CDateTimeFormat.dateTime().getParser();
     
      // Build the parser with the 3 sub-parsers.
      DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
      builder.append(null, parsers);
      ISO_W3C_DATE_TIME_PARSER = builder.toParser();
    }
   
    /*
     * (non-Javadoc)
     * @see org.joda.time.format.DateTimeParser#estimateParsedLength()
     */
    @Override
    public int estimateParsedLength() {
      return
        Math.max(
          ISO_W3C_DATE_PARSER.estimateParsedLength(),
          ISO_W3C_DATE_TIME_PARSER.estimateParsedLength());
    }
   
    /*
     * (non-Javadoc)
     * @see org.joda.time.format.DateTimeParser#parseInto(org.joda.time.format.DateTimeParserBucket, java.lang.String, int)
     */
    @Override
    public int parseInto(
        final DateTimeParserBucket bucket,
        final String text,
        final int position) {
     
      // Save the current state of the bucket.
      Object bucketState = bucket.saveState();
     
      // Attempt to parse the text with the date-only parser.
      int newPosition =
        ISO_W3C_DATE_PARSER.parseInto(bucket, text, position);
     
      // If the parser returned a negative number, that represents an
      // error and should be propagated.
      if(newPosition < 0) {
        return newPosition;
      }
      // If the new position is the length of the text, then the entire
      // string was parsed. We must set the time zone to UTC for these
      // values.
      else if(newPosition == text.length()) {
        bucket.setZone(DateTimeZone.UTC);
        return newPosition;
      }
      // Otherwise, this parser is inadequate and we must reset the
      // bucket and use the other parser.
      else {
        // FIXME: This shouldn't be necessary, and we should be able to
        // just continue parsing where we left off. If that were the
        // case, then this Parser could be removed as could the any()
        // function in the ISOW3CDateTimeFormat function, and users
        // could create any combination of the ISOW3CDateTimeFormats.
        bucket.restoreState(bucketState);
        return
          ISO_W3C_DATE_TIME_PARSER.parseInto(bucket, text, position);
      }
    }
  }
 
  // Lazily instantiate the internal formatters.
  private static DateTimeFormatter
    year,
    yearMonth,
    yearMonthDay,
    yearMonthDayHourMinuteZone,
    yearMonthDayHourMinuteSecondZone,
    yearMonthDayHourMinuteSecondMillisZone,
    any;

  /**
   * Default constructor. Does nothing.
   */
  protected ISOW3CDateTimeFormat() {
    super();
  }
 
  /**
   * Returns a formatter for the four digit year with a time zone of UTC.
   *
   * @return A formatter for the year with a time zone of UTC.
   */
  public static DateTimeFormatter year() {
    if(year == null) {
      year = ISODateTimeFormat.year().withZoneUTC();
    }
    return year;
  }
 
  /**
   * Returns a formatter for the four digit year and two digit month of
   * the year with a time zone of UTC.
   *
   * @return A formatter for the year and month with a time zone of UTC.
   */
  public static DateTimeFormatter yearMonth() {
    if(yearMonth == null) {
      yearMonth = ISODateTimeFormat.yearMonth().withZoneUTC();
    }
    return yearMonth;
  }
 
  /**
   * Returns a formatter for the four digit year, two digit month of the
   * year, and two digit day of the month with a time zone of UTC.
   *
   * @return A formatter for the year, month, and day with a time zone of
   *        UTC.
   */
  public static DateTimeFormatter yearMonthDay() {
    if(yearMonthDay == null) {
      yearMonthDay = ISODateTimeFormat.yearMonthDay().withZoneUTC();
    }
    return yearMonthDay;
  }
 
  /**
   * Returns a formatter for the four digit year, two digit month of the
   * year, and two digit day of the month with a time zone of UTC.
   *
   * @return A formatter for the year, month, and day with a time zone of
   *        UTC.
   */
  public static DateTimeFormatter date() {
    return yearMonthDay();
  }
 
  /**
   * Returns a formatter that combines a full date, two digit hour of the
   * day, two digit minute of the hour and a time zone.
   *
   * @return A formatter for the date, hour, minute, and time zone.
   */
  public static DateTimeFormatter dateHourMinuteZone() {
    if(yearMonthDayHourMinuteZone == null) {
      DateTimeFormatterBuilder dateHourMinuteTimezone =
        new DateTimeFormatterBuilder();
      dateHourMinuteTimezone
        .append(ISODateTimeFormat.dateHourMinute());
      dateHourMinuteTimezone.append(DateTimeFormat.forPattern("ZZ"));
      yearMonthDayHourMinuteZone =
        dateHourMinuteTimezone.toFormatter().withOffsetParsed();
    }
    return yearMonthDayHourMinuteZone;
  }
 
  /**
   * Returns a formatter that combines a full date, two digit hour of the
   * day, two digit minute of the hour, two digit second of the minute
   * and a time zone.
   *
   * @return A formatter for the date, hour, minute, second, and time
   *        zone.
   */
  public static DateTimeFormatter dateHourMinuteSecondZone() {
    if(yearMonthDayHourMinuteSecondZone == null) {
      yearMonthDayHourMinuteSecondZone =
        ISODateTimeFormat.dateTimeNoMillis().withOffsetParsed();
    }
    return yearMonthDayHourMinuteSecondZone;
  }
 
  /**
   * Returns a formatter that combines a full date, two digit hour of the
   * day, two digit minute of the hour, two digit second of the minute
   * and a time zone.
   *
   * @return A formatter for the date, hour, minute, second, and time
   *        zone.
   */
  public static DateTimeFormatter dateTimeNoMillis() {
    return dateHourMinuteSecondZone();
  }
 
  /**
   * Returns a formatter that combines a full date, two digit hour of the
   * day, two digit minute of the hour, two digit second of the minute,
   * three digit milliseconds of the second and a time zone.
   *
   * @return A formatter for the date, hour, minute, second, millisecond,
   *        and time zone.
   */
  public static DateTimeFormatter dateHourMinuteSecondMillisZone() {
    if(yearMonthDayHourMinuteSecondMillisZone == null) {
      yearMonthDayHourMinuteSecondMillisZone =
        ISODateTimeFormat.dateTime().withOffsetParsed();
    }
    return yearMonthDayHourMinuteSecondMillisZone;
  }
 
  /**
   * Returns a formatter that combines a full date, two digit hour of the
   * day, two digit minute of the hour, two digit second of the minute,
   * three digit milliseconds of the second and a time zone.
   *
   * @return A formatter for the date, hour, minute, second, millisecond,
   *        and time zone.
   */
  public static DateTimeFormatter dateTime() {
    return dateHourMinuteSecondMillisZone();
  }
 
  /**
   * Returns a formatter that combines all ISOW3CDateTimeFormats. This
   * formatter will correctly parse any of the other formatters and will only
   * fail if the value doesn't match any of them.
   *
   * @return A universal DateTimeFormatter for all ISO W3C date-time formats.
   *
   * @see #year()
   * @see #yearMonth()
   * @see #yearMonthDay()
   * @see #dateHourMinuteZone()
   * @see #dateHourMinuteSecondZone()
   * @see #dateHourMinuteSecondMillisZone()
   */
  public static DateTimeFormatter any() {
    if(any == null) {
      any =
        new DateTimeFormatter(
            ISODateTimeFormat.dateTime().getPrinter(),
            new ISOW3CDateTimeParser())
          .withOffsetParsed();
    }
    return any;
  }
}
TOP

Related Classes of org.openmhealth.reference.util.ISOW3CDateTimeFormat$ISOW3CDateTimeParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.