1 /* 2 * Copyright 1999,2006 The Apache Software Foundation. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.apache.commons.feedparser.tools; 18 19 import java.text.SimpleDateFormat; 20 import java.util.Date; 21 import java.util.Locale; 22 import java.util.TimeZone; 23 24 /** 25 * ISO 8601 date parsing utility. Designed for parsing the ISO subset used in 26 * Dublin Core, RSS 1.0, and Atom. 27 * 28 * @author <a href="mailto:burton@apache.org">Kevin A. Burton (burtonator)</a> 29 * @version $Id: ISO8601DateParser.java 373572 2006-01-30 19:28:41Z mvdb $ 30 */ 31 public class ISO8601DateParser { 32 33 // 2004-06-14T19:GMT20:30Z 34 // 2004-06-20T06:GMT22:01Z 35 36 private static SimpleDateFormat df 37 = new SimpleDateFormat( "yyyy-MM-dd'T'hh:mm:ssz", Locale.ENGLISH ); 38 39 // http://www.cl.cam.ac.uk/~mgk25/iso-time.html 40 // 41 // http://www.intertwingly.net/wiki/pie/DateTime 42 // 43 // http://www.w3.org/TR/NOTE-datetime 44 // 45 // Different standards may need different levels of granularity in the date and 46 // time, so this profile defines six levels. Standards that reference this 47 // profile should specify one or more of these granularities. If a given 48 // standard allows more than one granularity, it should specify the meaning of 49 // the dates and times with reduced precision, for example, the result of 50 // comparing two dates with different precisions. 51 52 // The formats are as follows. Exactly the components shown here must be 53 // present, with exactly this punctuation. Note that the "T" appears literally 54 // in the string, to indicate the beginning of the time element, as specified in 55 // ISO 8601. 56 57 // Year: 58 // YYYY (eg 1997) 59 // Year and month: 60 // YYYY-MM (eg 1997-07) 61 // Complete date: 62 // YYYY-MM-DD (eg 1997-07-16) 63 // Complete date plus hours and minutes: 64 // YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) 65 // Complete date plus hours, minutes and seconds: 66 // YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) 67 // Complete date plus hours, minutes, seconds and a decimal fraction of a 68 // second 69 // YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) 70 71 // where: 72 73 // YYYY = four-digit year 74 // MM = two-digit month (01=January, etc.) 75 // DD = two-digit day of month (01 through 31) 76 // hh = two digits of hour (00 through 23) (am/pm NOT allowed) 77 // mm = two digits of minute (00 through 59) 78 // ss = two digits of second (00 through 59) 79 // s = one or more digits representing a decimal fraction of a second 80 // TZD = time zone designator (Z or +hh:mm or -hh:mm) 81 public static Date parse( String input ) throws java.text.ParseException { 82 83 //NOTE: SimpleDateFormat uses GMT[-+]hh:mm for the TZ which breaks 84 //things a bit. Before we go on we have to repair this. 85 86 //this is zero time so we need to add that TZ indicator for 87 if ( input.endsWith( "Z" ) ) { 88 input = input.substring( 0, input.length() - 1) + "GMT-00:00"; 89 } else { 90 int inset = 6; 91 92 String s0 = input.substring( 0, input.length() - inset ); 93 String s1 = input.substring( input.length() - inset, input.length() ); 94 95 input = s0 + "GMT" + s1; 96 } 97 98 return df.parse( input ); 99 100 } 101 102 public static String toString( Date date ) { 103 104 TimeZone tz = TimeZone.getTimeZone( "UTC" ); 105 106 df.setTimeZone( tz ); 107 108 String output = df.format( date ); 109 110 int inset0 = 9; 111 int inset1 = 6; 112 113 String s0 = output.substring( 0, output.length() - inset0 ); 114 String s1 = output.substring( output.length() - inset1, output.length() ); 115 116 String result = s0 + s1; 117 118 result = result.replaceAll( "UTC", "+00:00" ); 119 120 return result; 121 122 } 123 124 public static void main( String[] args ) throws Exception { 125 126 System.out.println( parse( "2004-05-31T09:19:31-06:00" ) ); 127 System.out.println( parse( "2004-06-23T17:25:31-00:00" ) ); 128 System.out.println( parse( "2004-06-23T17:25:31Z" ) ); 129 130 //2002-10-02T10:00:00-05:00 131 System.out.println( "v: " + toString( new Date( System.currentTimeMillis() ) ) ); 132 133 } 134 135 } 136