Mega Code Archive

 
Categories / Java / Data Type
 

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 Benoît 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());   } }