/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.common.util; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import com.scooterframework.web.controller.ACH; /** * DateUtil class has helper methods for rendering date and time. * * <p> * Note: By the time of this version, the only allowed date-time patterns * for automatic form processing are listed in description of * {@link #getDateTimePattern(java.lang.String)} method.</p> * * @author (Fei) John Chen */ public class DateUtil { /** * <p>Returns a date instance from a <tt>dateStr</tt> string. * The date-time pattern needed for parsing will be detected from the input * <tt>dateStr</tt> string with the current locale.</p> * * <p> * Note: By the time of this version, the only allowed date-time patterns * for automatic form processing are listed in description of * {@link #getDateTimePattern(java.lang.String)} method.</p> * * @param dateStr date string * @return a date instance */ public static Date parseDate(String dateStr) { return parseDate(dateStr, getDateTimePattern(dateStr), ACH.getAC().getLocale()); } /** * <p>Returns a date instance from a <tt>dateStr</tt> string.</p> * * <p> * Note: By the time of this version, the only allowed date-time patterns * for automatic form processing are listed in description of * {@link #getDateTimePattern(java.lang.String)} method.</p> * * @param dateStr date string * @param pattern the pattern describing the date and time format * @return a date instance */ public static Date parseDate(String dateStr, String pattern) { return parseDate(dateStr, pattern, ACH.getAC().getLocale()); } /** * <p>Returns a date instance from a <tt>dateStr</tt> string. * The date-time pattern needed for parsing will be detected from the input * <tt>dateStr</tt> string</p> * * <p> * Note: By the time of this version, the only allowed date-time patterns * for automatic form processing are listed in description of * {@link #getDateTimePattern(java.lang.String)} method.</p> * * @param dateStr date string * @param locale locale for date * @return a date instance */ public static Date parseDate(String dateStr, Locale locale) { return parseDate(dateStr, getDateTimePattern(dateStr), locale); } /** * <p>Returns a date instance from a <tt>dateStr</tt> string. </p> * * <p> * Note: By the time of this version, the only allowed date-time patterns * for automatic form processing are listed in description of * {@link #getDateTimePattern(java.lang.String)} method.</p> * * @param dateStr date string * @param pattern the pattern describing the date and time format * @param locale locale for date * @return a date instance */ public static Date parseDate(String dateStr, String pattern, Locale locale) { if (dateStr == null || "".equals(dateStr)) return null; Date date = null; try { if (pattern == null || "".equals(pattern)) { pattern = getDateTimePattern(dateStr); if ("".equals(pattern)) return null; } if (locale == null) locale = ACH.getAC().getLocale(); SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale); date = sdf.parse(dateStr); } catch(ParseException pex) { throw new RuntimeException("Error in parseDate: " + pex.getMessage()); } return date; } /** * Returns a data time pattern string. * <pre> * slashDate: MM/dd/yyyy or MM/dd/yy * dashDate: yyyy-MM-dd * hourMinute: HH:mm * hourMinuteSecond: HH:mm:ss * hourMinuteSecondMilli: HH:mm:ss.SSS * dashDateHM: yyyy-MM-dd HH:mm * dashDateHMS: yyyy-MM-dd HH:mm:ss * dashDateHMSM: yyyy-MM-dd HH:mm:ss.SSS * slashDateHM: MM/dd/yyyy HH:mm or MM/dd/yy HH:mm * slashDateHMS: MM/dd/yyyy HH:mm:ss or MM/dd/yy HH:mm:ss * slashDateHMSM: MM/dd/yyyy HH:mm:ss.SSS or MM/dd/yy HH:mm:ss.SSS * </pre> * * @param dt a date time string * @return a data time pattern string */ public static final String getDateTimePattern(String dt) { String pattern = ""; try { if (checkParseable(dt)) { dt = dt.trim(); boolean hasDashDate = false; boolean hasSlashDate = false; boolean hasTime = false; if (dt.indexOf('-') != -1) hasDashDate = true; if (dt.indexOf('/') != -1) hasSlashDate = true; if (dt.indexOf(':') != -1) hasTime = true; if (hasDashDate && hasSlashDate) throw new Exception("Cannot have both dash and slash in the same date-time string."); if (hasDashDate) { String dateString = dt; String timePattern = ""; if (hasTime) { dateString = dt.substring(0, dt.indexOf(' ')); String timeString = dt.substring(dt.lastIndexOf(' ') + 1); timePattern = getTimePattern(timeString); } String datePattern = getDatePattern(dateString, '-'); if (hasTime) { pattern = datePattern + " " + timePattern; } else { pattern = datePattern; } } else if (hasSlashDate) { String dateString = dt; String timePattern = ""; if (hasTime) { dateString = dt.substring(0, dt.indexOf(' ')); String timeString = dt.substring(dt.lastIndexOf(' ') + 1); timePattern = getTimePattern(timeString); } String datePattern = getDatePattern(dateString, '/'); if (hasTime) { pattern = datePattern + " " + timePattern; } else { pattern = datePattern; } } else if (hasTime) { pattern = getTimePattern(dt); } } } catch(Exception ex) { ; } return pattern; } /** * <p> * checks if the date time string is parseable by this program. * </p> * * <p> * Note: By the time of this version, the only allowed date-time patterns * are in description of getDateTimePattern(String dt) method.</p> * * @param dt an input string * @return true if the string is parseable. */ private static boolean checkParseable(String dt) { if (dt == null || dt.length() == 0) return false; boolean state = true; int length = dt.length(); for (int i=0; i < length; i++) { char c = dt.charAt(i); if (ALLOWED_CHARS_FOR_DATETIME.indexOf(c) == -1) { state = false; break; } } return state; } private static String getTimePattern(String dt) throws Exception { int dtLength = (dt != null) ? dt.length() : 0; String timePattern = ""; if ((dtLength >= 3) && (dtLength <= 12)) { boolean hasTimeMilli = false; if (dt.indexOf('.') != -1) hasTimeMilli = true; int colonCount = 0; for (int i = 0; i < dtLength; i++) { char c = dt.charAt(i); if (c == ':') { colonCount++; } } if (colonCount == 1) { if (hasTimeMilli) throw new Exception("Unparseable date: \"" + dt + "\""); timePattern = "HH:mm"; } else if (colonCount == 2) { timePattern = (hasTimeMilli)? "HH:mm:ss.SSS":"HH:mm:ss"; } } return timePattern; } /** * The spliter must be either '-' or '/'. * * @return * @param spliter * @param dt */ private static String getDatePattern(String dt, char spliter) { int dtLength = (dt != null) ? dt.length() : 0; String datePattern = ""; if ((dtLength >= 6) && (dtLength <= 10)) { int spliterCount = 0; for (int i = 0; i < dtLength; i++) { char c = dt.charAt(i); if (c == spliter) { spliterCount++; } } if (spliterCount == 2) { if ('-' == spliter) { String year = dt.substring(0, dt.indexOf('-')); datePattern = (year.length()==2)?"yy-MM-dd":"yyyy-MM-dd"; } else if ('/' == spliter) { String year = dt.substring(dt.lastIndexOf('/') + 1); datePattern = (year.length()==2)?"MM/dd/yy":"MM/dd/yyyy"; } } } return datePattern; } private static String ALLOWED_CHARS_FOR_DATETIME = "0123456789-/:. "; }