Data Type Java

//package com.adobe.epubcheck.util;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.StringTokenizer;
import java.util.TimeZone;
/**
 * Date parser for the ISO 8601 format.
 * 
 * Initial code taken from the jigsaw project (W3C license [1]) and modified consistently to
 * apply further checks that were missing, for example the initial code reported 
 * 2011- as valid date. 
 * See also:
 * http://www.w3.org/TR/1998/NOTE-datetime-19980827
 * 
 * @author mircea@oxygenxml.com Initial version and fixes.
 * @author mihaela@sync.ro Initial version and fixes.
 * 
 * @author george@oxygenxml.com Additional fixes.
 */
 
/** 
 ***** [1] W3C license (jigsaw license) *****
 * 
 * Jigsaw Copying Conditions
 * 
 * W3C IPR SOFTWARE NOTICE
 * 
 * Copyright Â© 1995-1998 World Wide Web Consortium, (Massachusetts Institute of
 * Technology, Institut National de Recherche en Informatique et en
 * Automatique, Keio University). All Rights Reserved.
 * http://www.w3.org/Consortium/Legal/
 * 
 * This W3C work (including software, documents, or other related items) is
 * being provided by the copyright holders under the following license. By
 * obtaining, using and/or copying this work, you (the licensee) agree that you
 * have read, understood, and will comply with the following terms and
 * conditions:
 * 
 * Permission to use, copy, and modify this software and its documentation,
 * with or without modification,  for any purpose and without fee or royalty is
 * hereby granted, provided that you include the following on ALL copies of the
 * software and documentation or portions thereof, including modifications,
 * that you make:
 * 
 *   1. The full text of this NOTICE in a location viewable to users of the
 *      redistributed or derivative work.
 *   2. Any pre-existing intellectual property disclaimers, notices, or terms
 *      and conditions. If none exist, a short notice of the following form
 *      (hypertext is preferred, text is permitted) should be used within the
 *      body of any redistributed or derivative code: "Copyright Â© World Wide
 *      Web Consortium, (Massachusetts Institute of Technology, Institut
 *      National de Recherche en Informatique et en Automatique, Keio
 *      University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
 *   3. Notice of any changes or modifications to the W3C files, including the
 *      date changes were made. (We recommend you provide URIs to the location
 *      from which the code is derived).
 * 
 * In addition, creators of derivitive works must include the full text of this
 * NOTICE in a location viewable to users of the derivitive work.
 * 
 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS
 * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
 * PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE
 * ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
 * 
 * COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
 * CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
 * DOCUMENTATION.
 * 
 * The name and trademarks of copyright holders may NOT be used in advertising
 * or publicity pertaining to the software without specific, written prior
 * permission. Title to copyright in this software and any associated
 * documentation will at all times remain with copyright holders.
 * 
 * ____________________________________
 * 
 * This formulation of W3C's notice and license became active on August 14
 * 1998. See the older formulation for the policy prior to this date. Please
 * see our Copyright FAQ for common questions about using materials from our
 * site, including specific terms and conditions for packages like libwww,
 * Amaya, and Jigsaw. Other questions about this notice can be directed to
 * site-policy@w3.org .
 * 
 * 
 * 
 * 
 * webmaster
 * (last updated 14-Aug-1998)
 ***** end W3C license (jigsaw license) *****
 */
public class DateParser {
  /**
   * Check if the next token, if exists, has a given value and that the 
   * provided string tokenizer has more tokens after that. It consumes 
   * the token checked against the expected value from the string tokenizer.
   * 
   * @param st            The StringTokenizer to check. 
   * @param token         The value expected for the next token.
   * @return 
   *   true if the token matches the value and there are more tokens.
   *   false if there are no more tokens and we do not have a token to check.
   * @throws InvalidDateException If the token does not match the value or if there are no 
   * more tokens after the token that matches the expected value.
   */
  private boolean checkValueAndNext(StringTokenizer st, String token) throws InvalidDateException {
    if (!st.hasMoreTokens()) {
      return false;
    }
    String t = st.nextToken();
    if (!t.equals(token)) {
      throw new InvalidDateException("Unexpected: " + t);
    }
    if (!st.hasMoreTokens()) {
      throw new InvalidDateException("Incomplete date.");
    }
    return true;
  }
  /**
   * Check if a given date is an iso8601 date.
   * 
   * @param iso8601Date The date to be checked.
   * @return true if the date is an iso8601 date.
   * @throws InvalidDateException 
   */
  private Calendar getCalendar(String iso8601Date) throws InvalidDateException {
    // YYYY-MM-DDThh:mm:ss.sTZD
    StringTokenizer st = new StringTokenizer(iso8601Date, "-T:.+Z", true);
    if (!st.hasMoreTokens()) {
      throw new InvalidDateException("Empty Date");
    }
    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 (checkValueAndNext(st, "-")) {
        int month = Integer.parseInt(st.nextToken()) -1;
        calendar.set(Calendar.MONTH, month);
      } else {
        return calendar;
      }
      // Day
      if (checkValueAndNext(st, "-")) {
        int day = Integer.parseInt(st.nextToken());
        calendar.set(Calendar.DAY_OF_MONTH, day);
      } else {
        return calendar;
      }
      // Hour
      if (checkValueAndNext(st, "T")) {
        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 (checkValueAndNext(st, ":")) {
        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;
      }
      if (! st.hasMoreTokens()) {
        return calendar;
      }
      // Not mandatory now
      // Seconds
      String tok = st.nextToken();
      if (tok.equals(":")) { // seconds
        if (st.hasMoreTokens()) {
          int secondes = Integer.parseInt(st.nextToken());
          calendar.set(Calendar.SECOND, secondes);
          if (! st.hasMoreTokens()) {
            return calendar;
          }
          // decimal fraction of a second
          tok = st.nextToken();
          if (tok.equals(".")) {
            String nt = st.nextToken();
            while(nt.length() < 3) {
              nt += "0";
            }
            if (nt.length() > 3) {
              // check the other part from the decimal fraction to be formed only from digits
              for (int i=3; i                if (!Character.isDigit(nt.charAt(i))) {
                  throw new InvalidDateException("Invalid digit in the decimal fraction of a second: " + nt.charAt(i));
                }
              }
            }
            nt = nt.substring( 0, 3 ); //Cut trailing chars..
            int millisec = Integer.parseInt(nt);
            calendar.set(Calendar.MILLISECOND, millisec);
            if (! st.hasMoreTokens()) {
              return calendar;
            }
            tok = st.nextToken();
          } else {
            calendar.set(Calendar.MILLISECOND, 0);
          }
        } else {
          throw new InvalidDateException("No secondes specified");
        }
      } else {
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
      }
      // Time zone
      if (! tok.equals("Z")) { // UTC
        if (! (tok.equals("+") || tok.equals("-"))) {
          throw new InvalidDateException("only Z, + or - allowed");
        }
        boolean plus = tok.equals("+");
        if (! st.hasMoreTokens()) {
          throw new InvalidDateException("Missing hour field");
        }
        int tzhour = Integer.parseInt(st.nextToken());
        int tzmin  = 0;
        if (checkValueAndNext(st, ":")) {
          tzmin = Integer.parseInt(st.nextToken());
        } else {
          throw new InvalidDateException("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);
        }
      } else {
        if (st.hasMoreTokens()) {
          throw new InvalidDateException("Unexpected field at the end of the date field: " + st.nextToken());
        }
      }
    } catch (NumberFormatException ex) {
      throw new InvalidDateException("[" + ex.getMessage() + "] is not an integer");
    }
    return calendar;
  }
 
  /**
   * 
   * @param iso8601DateAsString The date parameter as a String.
   * @return The corresponding Date object representing the result of parsing the date parameter.
   * @throws InvalidDateException In case of an invalid date.
   */
  public Date parse(String iso8601DateAsString) throws InvalidDateException  {
      Calendar calendar = getCalendar(iso8601DateAsString);
      try {
        calendar.setLenient(false);
        return calendar.getTime();
      } catch (Exception e) {
        throw new InvalidDateException(iso8601DateAsString + " " + e.getClass().toString() + " " + e.getMessage());
      }
  }
}
class InvalidDateException extends Exception {
  /**
   * Creates an exception to signal an invalid date.
   * @param message
   */
  public InvalidDateException(String message) {
    super(message);
  }
}
  /**
   * Test the ISO8601 date. 
   * Date grammar: 
   *   Year: 
   *     YYYY (eg 1997) 
   *   Year and month: 
   *     YYYY-MM (eg 1997-07) 
   *   Complete date: 
   *     YYYY-MM-DD (eg 1997-07-16) 
   *   Complete date plus hours and minutes: 
   *     YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) 
   *   Complete date plus hours, minutes and seconds:
   *     YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) 
   *   Complete date plus hours, minutes, seconds and a decimal fraction of a second
   *     YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) 
   * where:
   * 
   * YYYY = four-digit year 
   * MM = two-digit month (01=January, etc.) 
   * DD = two-digit day of month (01 through 31) 
   * hh = two digits of hour (00 through 23) (am/pm NOT allowed) 
   * mm = two digits of minute (00 through 59)
   * ss = two digits of second (00 through 59) 
   * s = one or more digits representing a decimal fraction of a second 
   * TZD = time zone designator (Z or +hh:mm or -hh:mm)
   * 
   * @throws Exception
   */
/*
package com.adobe.epubcheck.util;
public class DateParserTest {
  public void testisISO8601Date() throws Exception {
    DateParser p = new DateParser();
    p.parse(  "2011"            );
    p.parse(  "2011-02"          );
    p.parse(  "2011-02-12"        );
    p.parse(  "2011-03-01T13"        );
    p.parse(  "2011-02-01T13:00"      );
    p.parse(  "2011-02-01T13:00:00"    );
    p.parse(  "2011-02-01T13:00:00Z"    );
    p.parse(  "2011-02-01T13:00:00+01:00"  );
    p.parse(  "2011-02-01T13:00:00-03:00"  );
    try {  
      p.parse(  ""              );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-"            );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-"          );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    try {  
      p.parse(  "2011-02-01T"        );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:"      );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:00:"      );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:00:00T"    );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:00:00+01"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:00:00+01:"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:00:00-03"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-01T13:00:00-03:"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    try {  
      p.parse(  "2011-02-01T13:00:00-03:AA"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    try {  
      p.parse(  "20a1"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    try {  
      p.parse(  " 2"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    try {  
      p.parse(  "2011-02-29"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    try {  
      p.parse(  "2011-02-01T13:00:00.123aqb"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    try {  
      p.parse(  "1994-11-05T13:15:30Zab"  );
      throw new Exception("Invaid date passed!");
    } catch (InvalidDateException e) {}
    
    
  }
  public static void main(String[] args) {
    try {
      new DateParserTest().testisISO8601Date();
      System.out.println("Passed all tests!");
    } catch (Exception e) {
      System.out.println("Fail:");
      e.printStackTrace();
    }
  }
}
*/