001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/sam/trunk/component/src/java/org/sakaiproject/tool/assessment/qti/util/Iso8601DateFormat.java $
003: * $Id: Iso8601DateFormat.java 9274 2006-05-10 22:50:48Z daisyf@stanford.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the"License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.tool.assessment.qti.util;
021:
022: import java.text.SimpleDateFormat;
023: import java.util.Calendar;
024: import java.util.Date;
025: import java.util.GregorianCalendar;
026: import java.util.TimeZone;
027: import java.util.regex.Matcher;
028: import java.util.regex.Pattern;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032:
033: import org.sakaiproject.tool.assessment.qti.exception.Iso8601FormatException;
034:
035: /**
036: * Based on ISO8601 Specification.
037: *
038: * @author <a href="mailto:lance@indiana.edu">Lance Speelmon</a>
039: * @version $Id: Iso8601DateFormat.java 9274 2006-05-10 22:50:48Z daisyf@stanford.edu $
040: */
041: public class Iso8601DateFormat {
042: public static final String BASIC_FORMAT = "yyyyMMdd'T'HHmmssZ";
043: private static Log log = LogFactory.getLog(Iso8601DateFormat.class);
044: private static final String GMT = "GMT";
045:
046: // 20031107T152420-0500 or
047: // 2003-11-07T15:24:20-05:00
048: private static final Pattern PATTERN_MATCH = Pattern
049: .compile("^(?:(\\d{2,4})-?)?" + // year
050: "(?:(\\d{2})-?)?" + // month
051: "(\\d{2})?" + // day of month
052: "T?" + // time separator
053: "(?:(\\d{2}):?)?" + // hour
054: "(?:(\\d{2}):?)?" + // minutes
055: "(\\d{2})?" + // seconds
056: "(Z?|(?:\\+|-).+)?$"); // timezone: -0500 or +08:00 or -05 or Z
057: private String pattern;
058:
059: /**
060: * Creates a new Iso8601DateFormat object.
061: */
062: public Iso8601DateFormat() {
063: log.debug("new Iso8601DateFormat()");
064: this .pattern = BASIC_FORMAT;
065: }
066:
067: /**
068: * DOCUMENT ME!
069: *
070: * @param simpleDateFormatPattern
071: *
072: * @see java.text.SimpleDateFormat
073: */
074: public Iso8601DateFormat(String simpleDateFormatPattern) {
075: log.debug("new Iso8601DateFormat(String " + pattern + ")");
076: this .pattern = simpleDateFormatPattern;
077: }
078:
079: /**
080: * DOCUMENTATION PENDING
081: *
082: * @param date DOCUMENTATION PENDING
083: *
084: * @return DOCUMENTATION PENDING
085: */
086: public String format(Date date) {
087: log.debug("format(Date " + date + ")");
088: SimpleDateFormat sdf = null;
089: if (this .pattern == null) {
090: sdf = new SimpleDateFormat();
091: } else {
092: sdf = new SimpleDateFormat(pattern);
093: }
094:
095: return sdf.format(date);
096: }
097:
098: /**
099: * DOCUMENTATION PENDING
100: *
101: * @param iso8601String DOCUMENTATION PENDING
102: *
103: * @return DOCUMENTATION PENDING
104: *
105: * @throws Iso8601FormatException DOCUMENTATION PENDING
106: */
107: public Calendar parse(String iso8601String)
108: throws Iso8601FormatException {
109: log.debug("parse(String " + iso8601String + ")");
110: if (iso8601String == null) {
111: throw new Iso8601FormatException(
112: "illegal String iso8601TimeInterval argument: "
113: + iso8601String);
114: }
115:
116: iso8601String = iso8601String.toUpperCase();
117: final Matcher matcher = PATTERN_MATCH.matcher(iso8601String);
118: if (matcher.matches()) {
119: if (log.isDebugEnabled()) {
120: for (int i = 0; i <= matcher.groupCount(); i++) {
121: log.debug(i + "=" + matcher.group(i));
122: }
123: }
124:
125: String tz = matcher.group(7);
126: Calendar cal = null;
127: if ((tz != null) && (tz.length() > 0)) {
128: if ("Z".equals(tz)) {
129: tz = "Zulu";
130: } else {
131: tz = GMT + tz;
132: }
133:
134: if (log.isDebugEnabled()) {
135: log.debug("tz=" + tz);
136: log.debug("TimeZone.getID()="
137: + TimeZone.getTimeZone(tz).getID());
138: }
139:
140: cal = GregorianCalendar.getInstance(TimeZone
141: .getTimeZone(tz));
142: } else {
143: cal = GregorianCalendar.getInstance();
144:
145: /* data must be zeroed out to counteract now behavior*/
146: cal.clear();
147: }
148:
149: /* year */
150: if (matcher.group(1) != null) {
151: final int year = Integer.parseInt(matcher.group(1));
152: cal.set(Calendar.YEAR, year);
153: } else {
154: throw new Iso8601FormatException("Year is required");
155: }
156:
157: /* month */
158: if (matcher.group(2) != null) {
159: final int month = Integer.parseInt(matcher.group(2)) - 1; // zero based
160: cal.set(Calendar.MONTH, month);
161: }
162:
163: /* date (day) */
164: if (matcher.group(3) != null) {
165: final int date = Integer.parseInt(matcher.group(3));
166: cal.set(Calendar.DAY_OF_MONTH, date);
167: }
168:
169: /* hour */
170: if (matcher.group(4) != null) {
171: final int hour = Integer.parseInt(matcher.group(4));
172: cal.set(Calendar.HOUR_OF_DAY, hour);
173: }
174:
175: /* minutes */
176: if (matcher.group(5) != null) {
177: final int min = Integer.parseInt(matcher.group(5));
178: cal.set(Calendar.MINUTE, min);
179: }
180:
181: /* seconds */
182: if (matcher.group(6) != null) {
183: final int sec = Integer.parseInt(matcher.group(6));
184: cal.set(Calendar.SECOND, sec);
185: }
186:
187: return cal;
188: }
189:
190: throw new Iso8601FormatException(
191: "ISO8601 format could not be matched");
192: }
193: }
|