/*
 *  
 */

package com.jware.util;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


/**
 * 日付汎用ユーティリティクラス
 * 
 * @author  $Id: DateUtils.java,v 1.1 2010/01/13 11:52:32 clmg Exp $
 */
public class DateUtils {

	private static final String DATE_FORMAT = "yyyy-MM-dd";

	private static final String FORMAT_FOR_YEAR = "yyyy";
	private static final String FORMAT_FOR_MONTH = "MM";
	private static final String FORMAT_FOR_DAY = "dd";

	private static final SimpleDateFormat mochaDateFormat = new SimpleDateFormat("yyyy-MM-dd");	
	private static final SimpleDateFormat mochaDateFormatWithTimeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm");
	private static Calendar cal = Calendar.getInstance();

	private DateUtils() {
	}

	/**
	 * 
	 */
	public static boolean isDate(String format, String argStr) {
		if (argStr == null || argStr.length() <= 0) {
			return false;
		}
		return isDate(format, argStr, true);
	}
	
	/**
	 * 
	 */
	public static boolean isDate(String format, String argStr, boolean nullable) {
		
		if (argStr == null || argStr.length() <= 0) {
			if (nullable) {
				return true;
			}
		}

		int pForYear = format.indexOf(FORMAT_FOR_YEAR);
		int pForMonth = format.indexOf(FORMAT_FOR_MONTH);
		int pForDay = format.indexOf(FORMAT_FOR_DAY);
		
		int pForYearMonthDeli = FORMAT_FOR_YEAR.length();
		int pForMonthDayDeli = pForMonth + FORMAT_FOR_MONTH.length();
		
		if (pForYear == -1 || pForMonth == -1 || pForDay == -1) {
			return false;
		}

		if( !(format.substring(pForYearMonthDeli,pForMonth).equals( argStr.substring(pForYearMonthDeli, pForMonth))) ){
			return false;
		}

		if( !(format.substring(pForMonthDayDeli,pForDay).equals( argStr.substring(pForMonthDayDeli, pForDay))) ){
			return false;
		}

		String dateStr = null;
		dateStr =
			argStr.substring(pForYear, FORMAT_FOR_YEAR.length())
				+ argStr.substring(pForMonth, pForMonth + FORMAT_FOR_MONTH.length())
				+ argStr.substring(pForDay, pForDay + FORMAT_FOR_DAY.length());

		try {
			int year = Integer.parseInt(dateStr.substring(0, 4));
			int month = Integer.parseInt(dateStr.substring(4, 6));
			if (month < 1 || month > 12) {
				return false;
			}
			int maxDay = 0;
			synchronized (cal) {
				cal.set(year, month - 1, 1);
				maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
			}
			int day = Integer.parseInt(dateStr.substring(6));
			if (1 <= day && day <= maxDay) {
				return true;
			}
		} catch (NumberFormatException nfe) {
			// ...
			return false;
		}
		return false;
	}

	/**
	 * yyyy-mm-ddの型にて妥当性チェックを行う。
	 * @param date 対象日付
	 * @return boolean true 妥当性がある場合
	 */
	public static boolean isDate(String date) {
		if( date == null )
			return false;
		if (date.length() != 10)
			return false;
		if (isDate(DATE_FORMAT, date))
			return true;
		return false;
	}

	/**
	 * yyyy-mm-ddの型にて妥当性チェックを行う。
	 * @param date 対象日付
	 * @param nullable NULLを許可するか。許可する場合で値がnullの場合はtrueを
	 * 返します。
	 * @return boolean true 妥当性がある場合
	 */
	public static boolean isDate(String date,boolean nullable) {
		if (( date == null ) || (date.length()==0))
			if (nullable) {
				return true;
			} else {
				return false;
			}
		if (date.length() != 10)
			return false;
		if (isDate(DATE_FORMAT, date))
			return true;
		return false;
	}
	/**
	 * yyyy-MM-dd形式の状態でチェックします
	 * 
	 */
	public static boolean isDateBeforeAfter(String date1,String date2) {
        
		if( date1 == null )
			return false;
		if( date2 == null )
			return false;
			
		if (date1.length() != 10)
			return false;
		if (!(isDate(DATE_FORMAT, date1)))
			return false;

		if (date2.length() != 10)
			return false;
		if (!(isDate(DATE_FORMAT, date2)))
			return false;
			
		//同じ日の場合は問題なし	
		if (date1.equals(date2)) {
			return true;
		}

		Date checkDate1 = convertToDate(date1);			
		Date checkDate2 = convertToDate(date2);			

		return (checkDate1.before(checkDate2) ? true : false);			

	}

	/**
	 * yyyy-MM-dd形式の状態でチェックします
	 * 
	 */
	public static boolean isDateBeforeAfterNull(String date1,String date2) {
        
		if (((date1 == null) || (date1.length()==0)) || 
		   ((date2 == null) || (date2.length()==0))) {
		   	return true;
		 }

		if (date1.equals(date2)) {
			return true;
		}

		Date checkDate1 = convertToDate(date1);			
		Date checkDate2 = convertToDate(date2);			

		return (checkDate1.before(checkDate2) ? true : false);			

	}

	/**
	 * 指定された日付の年を返します。
	 * @param date1
	 * @return
	 */
	public static int getYYYY(String date1) {

		if( date1 == null )
			return -1;
		int pForYear = DATE_FORMAT.indexOf(FORMAT_FOR_YEAR);
		int pForMonth = DATE_FORMAT.indexOf(FORMAT_FOR_MONTH);
		int pForDay = DATE_FORMAT.indexOf(FORMAT_FOR_DAY);

		return new Integer(date1.substring(pForYear, pForYear + FORMAT_FOR_YEAR.length())).intValue();

	}
	
	/**
	 * 指定された日付の月を返します。
	 * @param date1
	 * @return
	 */
	public static int getMM(String date1) {
	
		if( date1 == null )
			return -1;
		int pForYear = DATE_FORMAT.indexOf(FORMAT_FOR_YEAR);
		int pForMonth = DATE_FORMAT.indexOf(FORMAT_FOR_MONTH);
		int pForDay = DATE_FORMAT.indexOf(FORMAT_FOR_DAY);

		return new Integer(
			date1.substring(pForMonth, pForMonth + FORMAT_FOR_MONTH.length()))
			.intValue();

	}

	/**
	 * 指定された日付の日を返します。
	 * @param date1
	 * @return
	 */
	public static int getDD(String date1) {

		if( date1 == null )
			return -1;
		int pForYear = DATE_FORMAT.indexOf(FORMAT_FOR_YEAR);
		int pForMonth = DATE_FORMAT.indexOf(FORMAT_FOR_MONTH);
		int pForDay = DATE_FORMAT.indexOf(FORMAT_FOR_DAY);

		return new Integer(
			date1.substring(pForDay, pForDay + FORMAT_FOR_DAY.length()))
			.intValue();

	}

	/**
	 * 渡された日付をyyyy-MM-ddのStringで返します
	 */
	public static String getDateFormat(Date date) {
		if( date == null ) { 
			return null;
		}
		return mochaDateFormat.format(date);
	}
	
	/**
	 * 渡された日付をyyyy-MM-dd HH:mmのStringで返します
	 */
	public static String getDateFormatWithTimeStamp(Date date) {
		if( date == null ) { 
			return null;
		}
		return mochaDateFormatWithTimeStamp.format(date);
	}

	/**
	 * 渡された日付を format のStringで返します
	 */
	public static String getDateFormat(Date date, String format) {
		if( date == null ) { 
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat( format );	
		
		return dateFormat.format(date);
	}

	/**
	 * 渡された日付を"HH:mm:ss"フォーマットで返します
	 */
	public static String getTimeFormat(Date date) {
		if( date == null ) { 
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat( "HH:mm:ss" );	
		
		return dateFormat.format(date);
	}
	
	/**
	 * 渡された日付の時間をで返します
	 */
	public static String getHours(Date date) {
		if( date == null ) { 
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat( "HH" );	
		
		return dateFormat.format(date);
	}

	/**
	 * 渡された日付のをで返します
	 */
	public static String getMinutes(Date date) {
		if( date == null ) { 
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat( "mm" );	
		
		return dateFormat.format(date);
	}
	
	/**
	 * 渡された日付のをで返します
	 */
	public static String getSeconds(Date date) {
		if( date == null ) { 
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat( "ss" );	
		
		return dateFormat.format(date);
	}

	/**
	 * システム日付をyyyyMMのStringで返します
	 */
	public static String getYYYYMM() {

		String dateTmp = mochaDateFormat.format(new Date());

		String dateYM = dateTmp.substring(0, 4) + dateTmp.substring(5, 7);

		return dateYM;

	}

	/**
	 * システム日付の前月をyyyyMMのStringで返します
	 */
	public static String getPreviousYYYYMM() {

		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, -1);

		DecimalFormat fmt = new DecimalFormat("00");
		String mm = fmt.format(cal.get(Calendar.MONTH) + 1);

		String yy = new Integer(cal.get(Calendar.YEAR)).toString();

		return (yy + mm);

	}

	/**
	 * システム日付の前日を返します
	 */
	public static Date getPreviousDay() {

		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);

		DecimalFormat fmt = new DecimalFormat("00");
		String mm = fmt.format(cal.get(Calendar.MONTH) + 1);
		String yy = new Integer(cal.get(Calendar.YEAR)).toString();
		String dd = fmt.format(cal.get(Calendar.DATE));

		return convertToDate(yy + "-" + mm + "-" + dd);
	}

	/**
	  * String型のシステム日付(yyyymmdd)を取得する
	  * @return yyyymmdd システム日付(yyyymmdd形式)
	  */
	public static String getYYYYMMDD() {
		return getYYYYMMDD(new Date());
	}

	/**
	  * Date型の日付情報より、String型の日付(yyyymmdd)を取得する
	  * @param trialtime 日付
	  * @return yyyymmdd 日付(yyyymmdd形式)
	  */
	public static String getYYYYMMDD(Date trialtime) {

		if( trialtime == null ) { 
			return null;
		}
		
		String[] arr = getYYYYMMDDArray(trialtime);
		return arr[0] + arr[1] + arr[2];
	}

	/**
	  * システム日付(String型の配列)を取得する
	  * @return arr システム日付配列 arr = {"yyyy","mm","dd"}
	  */
	public static String[] getYYYYMMDDArray() {
		return getYYYYMMDDArray(new Date());
	}

	/** 
	  * Date型の日付情報を、String型の配列で取得する
	  * @param trialtime 日付
	  * @return arr 日付配列 arr = {"yyyy","mm","dd"}
	  */
	public static String[] getYYYYMMDDArray(Date trialtime) {

		if( trialtime == null ) { 
			return null;
		}
		
		String[] yyyymmddhhmiss = DateUtils.getYYYYMMDDHHMISSArray(trialtime);

		String[] arr = new String[3];
		arr[0] = yyyymmddhhmiss[0];
		arr[1] = yyyymmddhhmiss[1];
		arr[2] = yyyymmddhhmiss[2];
		return arr;
	}

	/** 
	  * Date型の日付情報を、String型の配列で取得する
	  * @param trialtime 日付
	  * @return arr 時刻配列 arr = {"hh","mi","ss"}
	  */
	public static String[] getHHMISSArray(Date trialtime) {

		if( trialtime == null ) { 
			return null;
		}
		
		String[] yyyymmddhhmiss = DateUtils.getYYYYMMDDHHMISSArray(trialtime);

		String[] arr = new String[3];
		arr[0] = yyyymmddhhmiss[3];
		arr[1] = yyyymmddhhmiss[4];
		arr[2] = yyyymmddhhmiss[5];
		return arr;
	}

	/** 
	  * システム日付情報を、String型の配列で取得する
	  * @param trialtime 日付
	  * @return arr システム日付配列 arr = {"yyyy","mm","dd","hh","mi","ss"}
	  */
	public static String[] getYYYYMMDDHHMISSArray() {

		return DateUtils.getYYYYMMDDHHMISSArray(new Date());
	}

	/** 
	  * Date型の日付情報を、String型の配列で取得する
	  * @param trialtime 日付
	  * @return arr 日付配列 arr = {"yyyy","mm","dd","hh","mi","ss"}
	  */
	public static String[] getYYYYMMDDHHMISSArray(Date trialtime) {

		if( trialtime == null ) { 
			return null;
		}
		
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(trialtime);

		int YYYY = calendar.get(java.util.Calendar.YEAR);
		int MM = calendar.get(java.util.Calendar.MONTH) + 1;
		int DD = calendar.get(java.util.Calendar.DAY_OF_MONTH);
		int HH = calendar.get(java.util.Calendar.HOUR_OF_DAY);
		int MI = calendar.get(java.util.Calendar.MINUTE);
		int SS = calendar.get(java.util.Calendar.SECOND);
		int SSS = calendar.get(java.util.Calendar.MILLISECOND);

		String yyyy = Integer.toString(YYYY);

		String mm;
		if (MM < 10) {
			mm = "0" + Integer.toString(MM);
		} else {
			mm = Integer.toString(MM);
		}

		String dd;
		if (DD < 10) {
			dd = "0" + Integer.toString(DD);
		} else {
			dd = Integer.toString(DD);
		}

		String hh;
		if (HH < 10) {
			hh = "0" + Integer.toString(HH);
		} else {
			hh = Integer.toString(HH);
		}

		String mi;
		if (MI < 10) {
			mi = "0" + Integer.toString(MI);
		} else {
			mi = Integer.toString(MI);
		}

		String ss;
		if (SS < 10) {
			ss = "0" + Integer.toString(SS);
		} else {
			ss = Integer.toString(SS);
		}
		String sss;
		if (SSS < 10) {
			sss = "00" + Integer.toString(SSS);
		} else if( SSS < 100 ){
			sss = "0" + Integer.toString(SSS);
		} else {
			sss = Integer.toString(SSS);
		}

		String[] arr = new String[7];
		arr[0] = yyyy;
		arr[1] = mm;
		arr[2] = dd;
		arr[3] = hh;
		arr[4] = mi;
		arr[5] = ss;
		arr[6] = sss;

		return arr;
	}

	/** 
	  * システム日付を、String型(yyyy-mm-dd hh:mi:ss形式)で取得する
	  * @return timeStamp システム日付(yyyy-mm-dd hh:mi:ss)形式
	  */
	public static String getTimeStamp() {

        String timeStamp = DateUtils.getTimeStamp(new Date());
		return timeStamp;
	}

	/** 
	  * Date型の日付情報を、String型(yyyy-mm-dd hh:mi:ss形式)で取得する
	  * @param trialtime 日付
	  * @return arr 日付(yyyy-mm-dd hh:mi:ss)形式
	  */
	public static String getTimeStamp(Date trialtime) {

		if( trialtime == null ) { 
			return null;
		}
		
		String[] arr = DateUtils.getYYYYMMDDHHMISSArray();
		String timeStamp = arr[0] + "-" + arr[1] + "-" + arr[2] + " " + arr[3] + ":" + arr[4] + ":" + arr[5];
		return timeStamp;
		
	}

	/** 
	  * String型の日付情報を、Date型に変換し取得する
	  * 年月日の形式が(yyyy-mm-dd or yyyy/mm/dd)の形式しか対応していない。
	  * @param year   年月日
	  * @return Date Date型の日付情報
	  */
	public static Date currentDate() { 

		return Calendar.getInstance().getTime();
	} 

	/** 
	  * String型の日付情報を、Date型に変換し取得する
	  * 年月日の形式が(yyyy-mm-dd or yyyy/mm/dd)の形式しか対応していない。
	  * @param year   年月日
	  * @return Date Date型の日付情報
	  */
	public static Date stringToDate(String yyyymmdd, String hhmmss ) { 

		String year = null;
		String month = null;
		String date = null;

		String hour = null;
		String minute = null;
		String second = null;


		if (yyyymmdd != null) {

			// (yyyyMMdd)形式の場合
			if (yyyymmdd.length() == 8) {
				year = yyyymmdd.substring(0, 4);
				month = yyyymmdd.substring(4, 6);
				date = yyyymmdd.substring(6, 8);

			} else {
				int index = -1;

				// (yyyy-MM-dd)形式の場合
				index = yyyymmdd.indexOf("-");
				if (index != -1) {
					String[] arr = yyyymmdd.split("-");
					if (arr.length == 3) {
						year = arr[0];
						month = arr[1];
						date = arr[2];
					}
				// (yyyy/MM/dd)形式の場合
				} else {
					index = yyyymmdd.indexOf("/");
					if (index != -1) {
						String[] arr = yyyymmdd.split("/");
						if (arr.length == 3) {
							year = arr[0];
							month = arr[1];
							date = arr[2];
						}
					}
				}
			}
		}
		

		if (hhmmss != null) {
			// (yyyyMMdd)形式の場合
			if (hhmmss.length() == 6) {
				hour = hhmmss.substring(0, 2);
				minute = hhmmss.substring(2, 2);
				second = hhmmss.substring(4, 2);

			} else {
				int index = -1;

				// (yyyy-MM-dd)形式の場合
				index = hhmmss.indexOf(":");
				if (index != -1) {
					String[] arr = yyyymmdd.split(":");
					if (arr.length == 3) {
						hour = arr[0].substring( 0, 2);
						minute = arr[1].substring( 0, 2);
						second = arr[2].substring( 0, 2);
					}
				}
			}
		}

		return DateUtils.stringToDate(year, month, date, hour, minute, second);

	}
	/** 
	  * String型の日付情報を、Date型に変換し取得する
	  * 年月日の形式が(yyyy-mm-dd or yyyy/mm/dd)の形式しか対応していない。
	  * @param year   年月日
	  * @return Date Date型の日付情報
	  */
	public static Date stringToDate(String yyyymmdd ) { 

		String year = null;
		String month = null;
		String date = null;

		String hour = null;
		String minute = null;
		String second = null;


		if (yyyymmdd != null && yyyymmdd.trim().length() > 0 ) {

			// (yyyyMMdd)形式の場合
			if (yyyymmdd.length() == 8) {
				year = yyyymmdd.substring(0, 4);
				month = yyyymmdd.substring(4, 6);
				date = yyyymmdd.substring(6, 8);

			} else {
				int index = -1;

				// (yyyy-MM-dd)形式の場合
				index = yyyymmdd.indexOf("-");
				if (index != -1) {
					String[] arr = yyyymmdd.split("-");
					if (arr.length == 3) {
						year = arr[0];
						month = arr[1];
						date = arr[2];
					}
				// (yyyy/MM/dd)形式の場合
				} else {
					index = yyyymmdd.indexOf("/");
					if (index != -1) {
						String[] arr = yyyymmdd.split("/");
						if (arr.length == 3) {
							year = arr[0];
							month = arr[1];
							date = arr[2];
						}
					}
				}
			}
        }
        if( year == null || month == null || date == null ) {
        	return null; 
        }
		
		return DateUtils.stringToDate(year, month, date, hour, minute, second);
	} 


	/** 
	  * String型の日付情報を、Date型に変換し取得する
	  * 年月日の形式が(yyyy-mm-dd or yyyy/mm/dd)の形式しか対応していない。
	  * @param year   年月日
	  * @param hour   時
	  * @param minute 分
	  * @param second 秒
	  * @return Date Date型の日付情報
	  */
	public static Date stringToDate(String yyyymmdd, String hour, String minute, String second) { 

        String year = null;
		String month = null;
		String date = null;

        if (yyyymmdd != null) {

			// (yyyyMMdd)形式の場合
			if (yyyymmdd.length() == 8) {
				year = yyyymmdd.substring(0, 4);
				month = yyyymmdd.substring(4, 6);
				date = yyyymmdd.substring(6, 8);

			} else {
				int index = -1;

				// (yyyy-MM-dd)形式の場合
				index = yyyymmdd.indexOf("-");
				if (index != -1) {
					String[] arr = yyyymmdd.split("-");
					if (arr.length == 3) {
						year = arr[0];
						month = arr[1];
						date = arr[2];
					}
				// (yyyy/MM/dd)形式の場合
				} else {
					index = yyyymmdd.indexOf("/");
					if (index != -1) {
						String[] arr = yyyymmdd.split("/");
						if (arr.length == 3) {
							year = arr[0];
							month = arr[1];
							date = arr[2];
						}
					}
				}
			}
        }
        if( year == null || month == null || date == null ) {
        	return null; 
        }
        
		return DateUtils.stringToDate(year, month, date, hour, minute, second);
	} 

	/** 
	  * String型の日付情報を、Date型に変換し取得する
	  * @param year   年
	  * @param month  月
	  * @param date   日
	  * @param hour   時
	  * @param minute 分
	  * @param second 秒
	  * @return Date Date型の日付情報
	  */
	public static Date stringToDate(String year, String month, String date, String hour, String minute, String second) { 

        if (year == null || "".equals( year.trim() )) {
			year = "0";
        }
		if (month == null || "".equals( month.trim() )) {
			month = "0";
		}
		if (date == null || "".equals( date.trim() )) {
			date = "0";
		}
		if (hour == null || "".equals( hour.trim() )) {
			hour = "0";
		}
		if (minute == null || "".equals( minute.trim() )) {
			minute = "0";
		}
		if (second == null || "".equals( second.trim() )) {
			second = "0";
		}

        int yyyy = Integer.parseInt(year, 10); 
        int mm   = Integer.parseInt(month, 10) - 1; 
        int dd   = Integer.parseInt(date, 10); 
		int hh   = Integer.parseInt(hour, 10); 
		int mi   = Integer.parseInt(minute, 10); 
		int ss   = Integer.parseInt(second, 10); 
		Calendar cal = new GregorianCalendar(yyyy, mm, dd, hh, mi, ss); 

        Date dateTime = new Date(cal.getTime().getTime());
        return dateTime;
	}
	
	/**
	 * "yyyy-MM-dd形式で変換を行う。
	 * 
	 */
	public static Date convertToDate(String dateString) {
		try {
			if (dateString.length()==10) {
				dateString = dateString.substring(0,4) + "-" + dateString.substring(5,7) + "-" + dateString.substring(8); 
			}
			SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
			fmt.setLenient(false);
			return fmt.parse(dateString);
		} catch (ParseException e) {
			throw new RuntimeException("Couldnt convert to Date. " + dateString, e);
		}
	}
	
	/**
	 * "yyyy-MM-dd形式で変換を行う。
	 * 
	 */
	public static Date convertToDate(String dateString, String format) {
		try {
			SimpleDateFormat fmt = new SimpleDateFormat(format);
			fmt.setLenient(false);
			return fmt.parse(dateString);
		} catch (ParseException e) {
			throw new RuntimeException("Couldnt convert to Date. " + dateString, e);
		}
	}
	
	
}
