package edu.umich.umms.util;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;

/**
 *  A bunch of utility methods for dates and calendars.
 */
public class DateUtil
{

private static SimpleDateFormat display2Format =
    new SimpleDateFormat ("MM/dd/yy");
private static SimpleDateFormat display4Format =
    new SimpleDateFormat ("MM/dd/yyyy");

/**
 *  Validate that a string represents a valid date. Returns
 *  java.util.Date or null if the date isn't valid.
 *  The format used to validate is MM/dd/yy as described in
 *  the API for <code>java.text.SimpleDateFormat</code>, although
 *  dashes are also allowed as delimiters.
 *  <p>
 *  Valid formats look like mm/dd/yy, mm/dd/yyyy. The month
 *  and days can be 1 or 2 digits. Years can be 2 or 4 digits.
 *  Two digit years are interpreted to be within a century of
 *  "now", adjusting dates to be within 80 years before and 20 years
 *  after "now".
 *
 *  @param inStr A string to be parsed into a date
 *  @return A Date or null.
 */
public static Date validateDateString (String inStr)
{
    Date outDt = null ;
    display2Format.setLenient(false);

    try
    {
        outDt = display2Format.parse (inStr.replace('-','/'));
    }
    catch (Exception ex) {}

    return outDt;
}

/**
 *  Validate that a string represents a valid calendar date.
 *  This method simply calls <code>DateUtil.validateDateString</code> and
 *  converts the returned <code>Date</code> into a <code>Calendar</code>.
 *
 *  @param inStr A string to be parsed into a calendar date
 *  @return A Calendar or null.
 */

public static Calendar validateCalendarString(String inStr)
{
    Calendar outCal = null;
    Date outDt = validateDateString(inStr);
    if (null != outDt)
    {
        outCal = Calendar.getInstance();
        outCal.setTime(outDt);
    }

    return outCal;
}

/**
 *  Render a <code>Date</code> as a <code>String</code> in
 *  a standard format of MM/dd/yyyy. If the date is null
 *  then the returned string is "".
 *
 *  @param inDate
 *  @return A string in the format MM/dd/yyyy
 */
public static String dateToString(Date inDt)
{
    String str = "";

    if (null != inDt)
        str = display4Format.format(inDt);
    
    return str;
}

/**
 *  A convenience method.
 *  @param inCalendar
 *  @return A string in the format MM/dd/yyyy
 */
public static String dateToString(Calendar inCalendar)
{
    return calendarToString(inCalendar);
}

/**
 *  Render a <code>Calendar</code> as a <code>String</code> in
 *  a standard format of MM/dd/yyyy. If the calendar is null
 *  then the returned string is "".
 *
 *  @param inCalendar
 *  @return A string in the format MM/dd/yyyy
 */
public static String calendarToString(Calendar inCalendar)
{
    String str = "";
    
    if (null != inCalendar)
        str = dateToString(inCalendar.getTime());
        
    return str;
}

/**
 *  A convenience method.
 *  @param inDate
 *  @return A string in the format MM/dd/yyyy
 */
public static String calendarToString(Date inDate)
{
    return dateToString(inDate);
}

/**
 *  Determine if a date is within a certain range, centered on
 *  now. Adds and subtracts the specified amount of the given
 *  time field to the current time, and determine if the given
 *  date is between those two times. For example, to determine
 *  if a date is within 3 days before or after now:
 *  <pre><code>
 *  DateUtil.withinRange(cal, Calendar.DAY_OF_YEAR, 2);
 *  </code></pre>
 *  @param cal The date you wish to test
 *  @param field the time field
 *  @param amount the amount of date or time to be added and 
 *      subtracted from now.
 */
public static boolean withinRange(Calendar cal, int field, int amount)
{
    Calendar now = Calendar.getInstance();
    Calendar before = (Calendar)now.clone();
    before.add(field, -amount);
    Calendar after = (Calendar)now.clone();
    after.add(field, amount);

    return cal.after(before) && cal.before(after);
}

}   // DateUtil