Date parser for ISO 8601 format : Date Parser « Data Type « Java






Date parser for ISO 8601 format

     
// DateParser.java
// $Id: DateParser.java,v 1.5 2005/05/16 10:19:19 ylafon Exp $
// (c) COPYRIGHT MIT, INRIA and Keio, 2000.
// Please first read the full copyright statement in file COPYRIGHT.html

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.TimeZone;

/**
 * Date parser for ISO 8601 format
 * http://www.w3.org/TR/1998/NOTE-datetime-19980827
 * 
 * @version $Revision: 1.5 $
 * @author Benot Mah (bmahe@w3.org)
 * @author Yves Lafon (ylafon@w3.org)
 */
public class DateParser {

  private static boolean check(StringTokenizer st, String token)

  {
    try {
      if (st.nextToken().equals(token)) {
        return true;
      } else {
        throw new RuntimeException("Missing [" + token + "]");
      }
    } catch (NoSuchElementException ex) {
      return false;
    }
  }

  private static Calendar getCalendar(String isodate) {
    // YYYY-MM-DDThh:mm:ss.sTZD
    StringTokenizer st = new StringTokenizer(isodate, "-T:.+Z", true);

    Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
    calendar.clear();
    try {
      // Year
      if (st.hasMoreTokens()) {
        int year = Integer.parseInt(st.nextToken());
        calendar.set(Calendar.YEAR, year);
      } else {
        return calendar;
      }
      // Month
      if (check(st, "-") && (st.hasMoreTokens())) {
        int month = Integer.parseInt(st.nextToken()) - 1;
        calendar.set(Calendar.MONTH, month);
      } else {
        return calendar;
      }
      // Day
      if (check(st, "-") && (st.hasMoreTokens())) {
        int day = Integer.parseInt(st.nextToken());
        calendar.set(Calendar.DAY_OF_MONTH, day);
      } else {
        return calendar;
      }
      // Hour
      if (check(st, "T") && (st.hasMoreTokens())) {
        int hour = Integer.parseInt(st.nextToken());
        calendar.set(Calendar.HOUR_OF_DAY, hour);
      } else {
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
      }
      // Minutes
      if (check(st, ":") && (st.hasMoreTokens())) {
        int minutes = Integer.parseInt(st.nextToken());
        calendar.set(Calendar.MINUTE, minutes);
      } else {
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
      }

      //
      // Not mandatory now
      //

      // Secondes
      if (!st.hasMoreTokens()) {
        return calendar;
      }
      String tok = st.nextToken();
      if (tok.equals(":")) { // secondes
        if (st.hasMoreTokens()) {
          int secondes = Integer.parseInt(st.nextToken());
          calendar.set(Calendar.SECOND, secondes);
          if (!st.hasMoreTokens()) {
            return calendar;
          }
          // frac sec
          tok = st.nextToken();
          if (tok.equals(".")) {
            // bug fixed, thx to Martin Bottcher
            String nt = st.nextToken();
            while (nt.length() < 3) {
              nt += "0";
            }
            nt = nt.substring(0, 3); // Cut trailing chars..
            int millisec = Integer.parseInt(nt);
            // int millisec = Integer.parseInt(st.nextToken()) * 10;
            calendar.set(Calendar.MILLISECOND, millisec);
            if (!st.hasMoreTokens()) {
              return calendar;
            }
            tok = st.nextToken();
          } else {
            calendar.set(Calendar.MILLISECOND, 0);
          }
        } else {
          throw new RuntimeException("No secondes specified");
        }
      } else {
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
      }
      // Timezone
      if (!tok.equals("Z")) { // UTC
        if (!(tok.equals("+") || tok.equals("-"))) {
          throw new RuntimeException("only Z, + or - allowed");
        }
        boolean plus = tok.equals("+");
        if (!st.hasMoreTokens()) {
          throw new RuntimeException("Missing hour field");
        }
        int tzhour = Integer.parseInt(st.nextToken());
        int tzmin = 0;
        if (check(st, ":") && (st.hasMoreTokens())) {
          tzmin = Integer.parseInt(st.nextToken());
        } else {
          throw new RuntimeException("Missing minute field");
        }
        if (plus) {
          calendar.add(Calendar.HOUR, -tzhour);
          calendar.add(Calendar.MINUTE, -tzmin);
        } else {
          calendar.add(Calendar.HOUR, tzhour);
          calendar.add(Calendar.MINUTE, tzmin);
        }
      }
    } catch (NumberFormatException ex) {
      throw new RuntimeException("[" + ex.getMessage() + "] is not an integer");
    }
    return calendar;
  }

  /**
   * Parse the given string in ISO 8601 format and build a Date object.
   * 
   * @param isodate
   *          the date in ISO 8601 format
   * @return a Date instance
   * @exception InvalidDateException
   *              if the date is not valid
   */
  public static Date parse(String isodate) {
    Calendar calendar = getCalendar(isodate);
    return calendar.getTime();
  }

  private static String twoDigit(int i) {
    if (i >= 0 && i < 10) {
      return "0" + String.valueOf(i);
    }
    return String.valueOf(i);
  }

  /**
   * Generate a ISO 8601 date
   * 
   * @param date
   *          a Date instance
   * @return a string representing the date in the ISO 8601 format
   */
  public static String getIsoDate(Date date) {
    Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
    calendar.setTime(date);
    StringBuffer buffer = new StringBuffer();
    buffer.append(calendar.get(Calendar.YEAR));
    buffer.append("-");
    buffer.append(twoDigit(calendar.get(Calendar.MONTH) + 1));
    buffer.append("-");
    buffer.append(twoDigit(calendar.get(Calendar.DAY_OF_MONTH)));
    buffer.append("T");
    buffer.append(twoDigit(calendar.get(Calendar.HOUR_OF_DAY)));
    buffer.append(":");
    buffer.append(twoDigit(calendar.get(Calendar.MINUTE)));
    buffer.append(":");
    buffer.append(twoDigit(calendar.get(Calendar.SECOND)));
    buffer.append(".");
    buffer.append(twoDigit(calendar.get(Calendar.MILLISECOND) / 10));
    buffer.append("Z");
    return buffer.toString();
  }

  /**
   * Generate a ISO 8601 date
   * 
   * @param date
   *          a Date instance
   * @return a string representing the date in the ISO 8601 format
   */
  public static String getIsoDateNoMillis(Date date) {
    Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
    calendar.setTime(date);
    StringBuffer buffer = new StringBuffer();
    buffer.append(calendar.get(Calendar.YEAR));
    buffer.append("-");
    buffer.append(twoDigit(calendar.get(Calendar.MONTH) + 1));
    buffer.append("-");
    buffer.append(twoDigit(calendar.get(Calendar.DAY_OF_MONTH)));
    buffer.append("T");
    buffer.append(twoDigit(calendar.get(Calendar.HOUR_OF_DAY)));
    buffer.append(":");
    buffer.append(twoDigit(calendar.get(Calendar.MINUTE)));
    buffer.append(":");
    buffer.append(twoDigit(calendar.get(Calendar.SECOND)));
    buffer.append("Z");
    return buffer.toString();
  }

  public static void test(String isodate) {
    System.out.println("----------------------------------");
    Date date = parse(isodate);
    System.out.println(">> " + isodate);
    System.out.println(">> " + date.toString() + " [" + date.getTime() + "]");
    System.out.println(">> " + getIsoDate(date));
    System.out.println("----------------------------------");
  }

  public static void test(Date date) {
    String isodate = null;
    System.out.println("----------------------------------");
    System.out.println(">> " + date.toString() + " [" + date.getTime() + "]");
    isodate = getIsoDate(date);
    System.out.println(">> " + isodate);
    date = parse(isodate);
    System.out.println(">> " + date.toString() + " [" + date.getTime() + "]");
    System.out.println("----------------------------------");
  }

  public static void main(String args[]) {
    test("1997-07-16T19:20:30.45-02:00");
    test("1997-07-16T19:20:30+01:00");
    test("1997-07-16T19:20:30+01:00");
    test("1997-07-16T12:20:30-06:00");
    test("1997-07-16T19:20");
    test("1997-07-16");
    test("1997-07");
    test("1997");
    test(new Date());
  }

}

   
    
    
    
    
  








Related examples in the same category

1.Date Utils
2.Date To String
3.Perform date validations
4.ISO 8601 date parsing utility.
5.Parses a string representing a date by trying a variety of different parsers.
6.Parses a time period into a long. Translates possible [msec|sec|min|h] suffixes
7.A method to get the current date as an array of components 0 = year, 1 = month, 2 = day
8.ISO 8601 date parsing utility. Designed for parsing the ISO subset used in Dublin Core, RSS 1.0, and Atom.
9.A simple XML parser that starts parsing right away and validates along the way.