/* CPSDateValidator.java - created: Jan 30, 2008 * Copyright (C) 2008 Clayton Carter * * This file is part of the project "Crop Planning Software". For more * information: * website: https://github.com/claytonrcarter/cropplanning * email: cropplanning@gmail.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package CPS.Data; import CPS.Module.CPSGlobalSettings; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; public class CPSDateValidator { /** Example: 11/23 */ final public static int DATE_FORMAT_SHORT = 1; /** Example: Mon 11/23 */ final public static int DATE_FORMAT_SHORT_DAY_OF_WEEK = 2; /** Example: 11/23/13 */ final public static int DATE_FORMAT_BRIEFYEAR = 3; /** Example: 11/23/2013 */ final public static int DATE_FORMAT_FULLYEAR = 4; /** Example: Mon 11/23/2013 */ final public static int DATE_FORMAT_FULLYEAR_DAY_OF_WEEK = 5; /** Example: Nov 23 */ final public static int DATE_FORMAT_MON_DAY = 6; /** Example: Nov 23, 2013 */ final public static int DATE_FORMAT_MON_DAY_YEAR = 7; /** Example: November */ final public static int DATE_FORMAT_JUSTMONTH = 8; /** Example: 2013-11-23 */ final public static int DATE_FORMAT_SQL = 9; private static List<Integer> formatList; private static int defaultFormat; public CPSDateValidator() { formatList = new ArrayList<Integer>(); formatList.addAll( Arrays.asList( DATE_FORMAT_BRIEFYEAR, DATE_FORMAT_SHORT, DATE_FORMAT_FULLYEAR )); defaultFormat = DATE_FORMAT_FULLYEAR; } /** * @param formatNum - DATE_FORMAT_SHORT, DATE_FORMAT_SHORT_DAY_OF_WEEK, etc * @return a string format suitable for passing to format(Date,String) */ public static String getFormat( int formatNum ) { switch ( formatNum ) { case DATE_FORMAT_SHORT_DAY_OF_WEEK: if ( CPSGlobalSettings.useUSDates() ) return "EEE MM/dd"; else return "EEE dd/MM"; case DATE_FORMAT_BRIEFYEAR: if ( CPSGlobalSettings.useUSDates() ) return "MM/dd/yy"; else return "dd/MM/yy"; case DATE_FORMAT_FULLYEAR: if ( CPSGlobalSettings.useUSDates() ) return "MM/dd/yyyy"; else return "dd/MM/yyyy"; case DATE_FORMAT_FULLYEAR_DAY_OF_WEEK: if ( CPSGlobalSettings.useUSDates() ) return "EEE MM/dd/yyyy"; else return "EEE dd/MM/yyyy"; case DATE_FORMAT_MON_DAY: return "MMM dd"; case DATE_FORMAT_MON_DAY_YEAR: return "MMM dd, yyyy"; case DATE_FORMAT_JUSTMONTH: return "MMMM"; case DATE_FORMAT_SQL: return "yyyy-MM-dd"; case DATE_FORMAT_SHORT: default: if ( CPSGlobalSettings.useUSDates() ) return "MM/dd"; else return "dd/MM"; } } /** * Add a date format. * @param f a format string for SimpleDateFormat * @see java.text.SimpleDateFormat */ public void addFormat( Integer f ) { formatList.add(f); } /** * Sets the default format used for formatting dates. The default value * is DATE_FORMAT_FULLYEAR. * @param f Format to use. */ public void setDefaultFormat( Integer f ) { defaultFormat = f; } /** * Takes a Date and returns a formated String. Uses the default format. * @param d Date to format * @return Formatted string */ public static String format( Date d ) { return format( d, getFormat( defaultFormat )); } /** * Takes a Date and returns a formated String. * @param d Date to format * @param f One of DATE_FORMAT_SHORT, etc * @return Formatted string */ public static String format( Date d, Integer f ) { return format( d, getFormat( f )); } /** * Takes a Date and returns a formated String. * @param d Date to format * @param format String format to squish the Date into. * @return Formatted string */ public static String format( Date d, String format ) { if ( d == null || d.getTime() == 0 ) return ""; else return new SimpleDateFormat( format ).format( d ); } public static Date simpleParse( String s ) { return simpleParse( s, getFormat( defaultFormat )); } /** * @param s A String representation of a date to parse. * @param format Date format to parse it against. (Such as the (@link DATE_FORMAT_* } defined in this class. * @return the parsed date. */ public static Date simpleParse( String s, String format ) { if ( s == null || s.equals( "" )) return null; else try { return new SimpleDateFormat( format ).parse( s ); } catch ( Exception e ) { e.printStackTrace(); return null; } } public static Date parse( String s ) { if ( s.equals( "" )) return null; Date date = new Date(-1); SimpleDateFormat sdf = new SimpleDateFormat(); sdf.setLenient(false); String dateText = s; int dateShift = 0; int shiftBy = GregorianCalendar.DAY_OF_YEAR; // handles addition of negative numbers if ( dateText.matches( ".+\\+.+" ) || dateText.matches( ".+-.+" ) ) { String[] sp = new String[] { "", "" }; int shiftFactor = 1; if ( dateText.matches( ".+\\+.+" )) { sp = dateText.split( "\\+" ); shiftFactor = 1; } // does NOT handle subtract of negative numbers else if ( dateText.matches( ".+-.+" ) ) { sp = dateText.split( "-" ); shiftFactor = -1; // if we split into two, then there was just one - if ( sp.length != 2 ) System.err.println( "ERROR(CPSDateValidator): Can't understand date:" + dateText + " [Too many '-'s]" ); } // trim off leading and trailing whitespace dateText = sp[0].trim(); String dateShiftString = sp[1].trim(); if ( dateShiftString.matches( ".+[dwmy]" )) { // we match on w or m; trailing whitespace was already trimmed // d isn't necessary since it's default if ( dateShiftString.matches( ".+w" )) shiftBy = GregorianCalendar.WEEK_OF_YEAR; else if ( dateShiftString.matches( ".+m" )) shiftBy = GregorianCalendar.MONTH; else if ( dateShiftString.matches( ".+y" )) shiftBy = GregorianCalendar.YEAR; // trim off the trailing character (the d, w or m) dateShiftString = dateShiftString.substring( 0, dateShiftString.length() - 1 ); } dateShift = shiftFactor * Integer.parseInt( dateShiftString ); } for ( Integer f : formatList ) { String format = getFormat(f); sdf.applyPattern( format ); try { // if the date parses, then break the for loop date = sdf.parse( dateText ); // System.out.println("DATE MATCHED: " + format ); // if the matched format doesn't include a year component, // then shift the date into this year. if ( format.indexOf("yy") == -1 ) { GregorianCalendar c = new GregorianCalendar(); GregorianCalendar now = new GregorianCalendar(); c.setTime( date ); now.setTime( new Date() ); c.set( GregorianCalendar.YEAR, now.get( GregorianCalendar.YEAR ) ); date = c.getTime(); } break; } // if the date doesn't parse, try the next pattern catch ( Exception ignore ) {} System.err.println( "ERROR parsing date: " + s ); } // if dateShift is not 0, then we should add it to the parsed date if ( dateShift != 0 ) { GregorianCalendar cal = new GregorianCalendar(); cal.setTime( date ); cal.add( shiftBy, dateShift ); date = cal.getTime(); } return date; } }