001: /*
002: * <copyright>
003: *
004: * Copyright 1997-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026:
027: package org.cougaar.util;
028:
029: import java.text.SimpleDateFormat;
030: import java.util.Calendar;
031: import java.util.Date;
032:
033: /**
034: * Short form date formatter, using "month/day/year" (e.g. 10/20/1999).
035: * <p>
036: * Easier to use and does better error checking than
037: * <code>java.text.SimpleDateFormat</code>.
038: * <p>
039: * See method <code>main()</code> at end for sample usage.
040: */
041:
042: public class ShortDateFormat {
043:
044: protected SimpleDateFormat myDateFormat;
045:
046: public ShortDateFormat() {
047: myDateFormat = new SimpleDateFormat("MM/dd/yyyy");
048: }
049:
050: /**
051: * @param date date to convert to string
052: * @return date string
053: */
054: public String toString(Date date) {
055: return myDateFormat
056: .format(
057: ((date != null) ? date : new Date()),
058: new StringBuffer(""),
059: new java.text.FieldPosition(
060: SimpleDateFormat.YEAR_FIELD))
061: .toString();
062: }
063:
064: /**
065: * Helper for adjusting a given date.
066: * <p>
067: * @param date date to adjust (current date if null)
068: * @param months adjust by number of months
069: * @param days adjust by number of days
070: * @return adjusted date
071: */
072: public static Date adjustDate(Date date, int months, int days) {
073: if (date == null)
074: date = new Date();
075: if ((months != 0) || (days != 0)) {
076: Calendar cal = Calendar.getInstance();
077: cal.setTime(date);
078: if (months != 0)
079: cal.add(Calendar.MONTH, months);
080: if (days != 0)
081: cal.add(Calendar.DATE, days);
082: date = cal.getTime();
083: }
084: return date;
085: }
086:
087: /**
088: * Helper for filling hour:minute:second of a given date to
089: * current hour:minute:second, since default is 0:00:00
090: * <p>
091: * @param date date needing hour:minute:second
092: * @return filled date
093: */
094: public static Date fixTime(Date date) {
095: if (date == null)
096: date = new Date();
097: else {
098: Calendar cal = Calendar.getInstance();
099: cal.setTime(date);
100: Calendar nowCal = Calendar.getInstance();
101: cal.set(Calendar.HOUR_OF_DAY, nowCal
102: .get(Calendar.HOUR_OF_DAY));
103: cal.set(Calendar.MINUTE, nowCal.get(Calendar.MINUTE));
104: cal.set(Calendar.SECOND, nowCal.get(Calendar.SECOND));
105: date = cal.getTime();
106: }
107: return date;
108: }
109:
110: /**
111: * @param sDate Short date string (e.g. "10/20/1999")
112: * @return Corresponding Date
113: */
114: public Date toDate(String sDate) {
115: return toDate(sDate, true);
116: }
117:
118: /**
119: * @param sDate Short date string (e.g. "10/20/1999")
120: * @param doFixTime if true then adjust hour:minute to current hour:minute
121: * @return Corresponding Date
122: */
123: public Date toDate(String sDate, boolean doFixTime) {
124: Date theDate = null;
125: if (isValid(sDate)) {
126: try {
127: // parse
128: theDate = myDateFormat.parse(sDate,
129: new java.text.ParsePosition(0));
130: if (doFixTime)
131: theDate = fixTime(theDate);
132: } catch (Exception badDateE) {
133: }
134: }
135: return theDate;
136: }
137:
138: /**
139: * <code>DateFormat</code> seems to do a lousy job at parsing the
140: * date -- it allows all sorts of mistakes (e.g. "12/12/1x944", etc).
141: * What we want in BNF is:<br>
142: * digit := ('0'..'9')<br>
143: * slash := '/'<br>
144: * days := (digit | (digit digit))<br>
145: * months := (digit | (digit digit))<br>
146: * years := (digit digit digit digit)<br>
147: * date := months slash days slash years<br>
148: * We'll let the myDateFormatter check the digit values.
149: * <p>
150: * Note: Doesn't check values! "99/99/9999" is "valid"!
151: * <p>
152: * @param sDate Short date string (e.g. "10/20/1999")
153: * @return true if sDate format is valid
154: */
155: protected static boolean isValid(String sDate) {
156: if (sDate == null)
157: return false;
158: // BEGIN
159: int iPos = 0;
160: // 1 or 2 digits
161: iPos = readDigits(sDate, iPos, 1, 2);
162: if (iPos < 0)
163: return false;
164: // slash
165: if ((iPos >= sDate.length()) || (sDate.charAt(iPos) != '/'))
166: return false;
167: // 1 or 2 digits
168: iPos = readDigits(sDate, iPos + 1, 1, 2);
169: if (iPos < 0)
170: return false;
171: // slash
172: if ((iPos >= sDate.length()) || (sDate.charAt(iPos) != '/'))
173: return false;
174: // 4 digits
175: iPos = readDigits(sDate, iPos + 1, 4, 4);
176: if (iPos < 0)
177: return false;
178: // END
179: if (iPos != sDate.length())
180: return false;
181: // VALID
182: return true;
183: }
184:
185: /**
186: * read digits from given string and starting position. check that
187: * the given range of digits were read.
188: */
189: protected static int readDigits(String s, int iStart,
190: int minDigits, int maxDigits) {
191: int iCurrent;
192: for (iCurrent = iStart; ((iCurrent < s.length()) && (Character
193: .isDigit(s.charAt(iCurrent)))); iCurrent++)
194: ;
195: int iDiff = iCurrent - iStart;
196: if ((iDiff < minDigits) || (iDiff > maxDigits))
197: return -1;
198: return iCurrent;
199: }
200: }
|