# 日期相關的處理方法 package com.cathay.common.util; import java.math.BigDecimal; import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.StringTokenizer; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import org.apache.log4j.Logger; /** * 日期相關的處理方法。 * @author Chris Wang * @version V1.0 (2001/09/29) * <BR> * <BR><B>Updated:</B> * <BR> * <BR><B>01.</B> 91/03/12 BingYi Lin 新增 toROCFormat 將西元年日期轉換為民國年特定格式。 * <BR> * */ @SuppressWarnings("unchecked") public class DATE { private static Logger logger = Logger.getLogger(DATE.class); public static final String[] aryROCUnits = { "十", "百", "年", "月", "日" }; public static final String[] aryROCNumber = { "", "一", "二", "三", "四", "五", "六", "七", "八", "九", "零" }; private static final String FIRST_DATE = "01"; private static int[] GENERAL_MONTH_DAY = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; private static int[] LEAP_YEAR_MONTH_DAY = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; private static final BigDecimal BD_86400000 = new BigDecimal("86400000"); /**星期幾*/ private static final int DATE_OF_WEEK_ARRAY[] = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY }; /**星期幾中文*/ private static final String DATE_OF_WEEK_CONVER[] = { "日", "一", "二", "三", "四", "五", "六" }; /**此class不需要被new出實體*/ private DATE() { } /** * 取得西元年今天的日期(YYYY-MM-DD)。 * @return 西元年日期(YYYY-MM-DD)。 */ public static String getY2KDate() { DateFormat my = new SimpleDateFormat("yyyy-MM-dd"); return my.format(new Date()); } /** * 取得民國年日期。 * @return 民國年日期。 * */ public static String getROCDate() { DateFormat my = new SimpleDateFormat("yyyyMMdd"); String today = my.format(new Date()); today = new Integer(new Integer(today.substring(0, 4)).intValue() - 1911).toString() + today.substring(4, 8); return today; } /** * 將傳入之民國年日期轉換為西元年日期(yyyy-MM-dd)。 * @param date 民國年日期格式僅能為「yyyMMdd」 * @return 西元年日期(yyyy-MM-dd)。 */ public static String toY2KDate(String date) { return toY2KDate(date, false); } /** * 將傳入之民國年日期轉換為西元年日期(yyyy-MM-dd)。 * @param date 民國年日期格式僅能為「yyyMMdd」,當 hasDelimiter 傳入 true 時可接受分隔符號(例如:yyy-MM-dd、yyy/MM/dd)。 * @param hasDelimiter * @return 西元年日期(yyyy-MM-dd)。 */ public static String toY2KDate(String date, boolean hasDelimiter) { if (date == null) { throw new IllegalArgumentException("DATE.toY2KDate() 傳數參數值為null"); } date = date.trim(); StringBuilder sb_year = new StringBuilder(); StringBuilder sb = new StringBuilder(); int flag = 0; for (int i = date.length() - 1; i >= 0; i--) { char c = date.charAt(i); // 排除非數字之字元 if (!Character.isDigit(c)) { if (!hasDelimiter) { throw new IllegalArgumentException("民國年月日格式有誤,不得傳入任何分隔符號"); } continue; } flag++; if (flag < 5) {// 後 4 碼為月及日 if (flag == 3) {// 第 3 碼開始為月,故先加入分隔符號 sb.insert(0, '-'); } sb.insert(0, c); } else {// 其餘視為年 if (flag == 5) {// 開始處理年前,先加入分隔符號 sb.insert(0, '-'); } sb_year.insert(0, c); } } if (sb_year.length() == 0) { throw new IllegalArgumentException("傳入參數無法解析為民國年月日[" + date + "]"); } sb.insert(0, Integer.parseInt(sb_year.toString()) + 1911); return sb.toString(); } /** * 將傳入之西元年日期(YYYY-MM-DD)轉換為民國年日期。 * @return 民國年日期。 * @param date 西元年日期(YYYY-MM-DD)。 */ public static String toROCDate(String date) { //DB2之日期格式為10碼 if (date == null || date.length() != 10) { throw new IllegalArgumentException("DATE.toROCDate() 傳數參數值為null或長度不為10"); } StringBuffer sbf = new StringBuffer(); sbf.append(Integer.toString(Integer.parseInt(date.substring(0, 4)) - 1911)).append(date.substring(5, 7)).append( date.substring(8, 10)); return sbf.toString(); } /** * 將傳入之西元年日期(YYYY-MM-DD)轉換為民國年特定格式。 * @return 民國年日期 91/02/01。 * @param date 西元年日期(YYYY-MM-DD)。 * @param del 分隔符號/。 */ public static String toROCFormat(String date, String del) { //DB2之日期格式為10碼 if (date == null || date.length() != 10) { throw new IllegalArgumentException("DATE.toROCFormat() 傳數參數 date 值為 null ,長度不為 10"); } if (!isDate(date, false)) { throw new IllegalArgumentException("DATE.toROCFormat() 傳數參數 date 值日期不存在"); } if (del == null) { throw new IllegalArgumentException("DATE.toROCFormat() 傳數參數 del 值為 null"); } StringBuffer sb = new StringBuffer(); sb.append(Integer.toString(Integer.parseInt(date.substring(0, 4)) - 1911)); sb.append(del); sb.append(date.substring(5, 7)); sb.append(del); sb.append(date.substring(8, 10)); String strRoc = sb.toString(); return strRoc; } /** * 取得目前之系統時間(HH:MM:SS)。 * @return 系統時間。 * */ public static String getTime() { DateFormat my = new SimpleDateFormat("hh:mm:ss"); String time = my.format(new Date()); return time; } /** * 取得目前之系統時間(24 (0~23) 小時之型式)(HH:MM:SS)。 * * @return 系統時間(24小時之型式)。 * */ public static String getTime24() { DateFormat my = new SimpleDateFormat("HH:mm:ss"); String time = my.format(new Date()); return time; } /** * <pre> * 計算兩日期之間相差天數。 * 回傳結果是 date2 - date1 有正負號之分。 * 使用範例: *   DATE.diffDay("1930-08-30", "1930-08-01"),return -29 *   DATE.diffDay("2010-08-30", "2010-09-02"),return 3 * </pre> * @param date1 開始日期(西元年日期(YYYY-MM-DD))。 * @param date2 結束日期(西元年日期(YYYY-MM-DD))。 * @return 兩日期之間相差數。 */ public static int diffDay(String date1, String date2) { Calendar cal = Calendar.getInstance(); if (!DATE.isDate(date1, false)) { throw new IllegalArgumentException("DATE.diffDay() 開始日期 參數值為 null ,長度不為 10 或日期不存在"); } if (!DATE.isDate(date2, false)) { throw new IllegalArgumentException("DATE.diffDay() 結束日期 參數值為 null,長度不為 10 或日期不存在"); } cal.set(Integer.parseInt(date1.substring(0, 4)), Integer.parseInt(date1.substring(5, 7)) - 1, Integer.parseInt(date1.substring(8, 10)), 0, 0, 0); Date diffDate1 = cal.getTime(); cal.set(Integer.parseInt(date2.substring(0, 4)), Integer.parseInt(date2.substring(5, 7)) - 1, Integer.parseInt(date2.substring(8, 10)), 0, 0, 0); Date diffDate2 = cal.getTime(); return diffDay(diffDate1, diffDate2); // return new BigDecimal(String.valueOf(time2)).subtract(new BigDecimal(String.valueOf(time1))).divide(BD_86400000, 0, BigDecimal.ROUND_HALF_UP).intValue(); } /** * <pre> * 計算兩日期之間相差天數。 * 回傳結果是 date2 - date1 有正負號之分。 * 當所傳入的 java.util.Date 若是包含時間(如:new java.util.Date()),則會一併納入時間進行比較,例如: * 2013-09-25 與 2013-09-25 比較時,相差 0 天 * 2013-09-25 15:00:00 與 2013-09-25 比較時,則會變為相差 1 天 * </pre> * @param date1 開始日期。 * @param date2 結束日期。 * @return 兩日期之間相差數。 */ public static int diffDay(Date date1, Date date2) { return new BigDecimal(String.valueOf(date2.getTime())).subtract(new BigDecimal(String.valueOf(date1.getTime()))).divide( BD_86400000, 0, BigDecimal.ROUND_HALF_UP).intValue(); } /** * 檢核傳入之日期是否為閏年 * @param date 傳入之日期(西元年日期(YYYY-MM-DD))。 * @return true:是閏年,false:不是閏年。 */ public static boolean isLeap(String date) { if (date == null || date.length() < 4) { throw new IllegalArgumentException("DATE.isLeap() 參數date為空或格式錯誤"); } int intYY = Integer.parseInt(date.substring(0, 4)); return isLeap(intYY); } /** * 檢查輸入年是否為潤年 * @param year * @return true:是閏年,false:不是閏年。 */ public static boolean isLeap(int year) { if (year % 4 == 0) { if (year % 100 == 0) { if (year % 400 == 0) { return true; } } else { return true; } } return false; } /** * 對傳入之日期進行年、月、日的加減運算。 * @return 運算過後之日期(西元年日期(YYYY-MM-DD))。 * @param date 欲運算之日期(西元年日期)yyyy-MM-dd。 * @param year 年(正數為加,負數為減)。 * @param month 月(正數為加,負數為減)。 * @param day 日(正數為加,負數為減)。 */ public static String addDate(String date, int year, int month, int day) { //DB2之日期格式為10碼 if (!isDate(date, false)) { throw new IllegalArgumentException("DATE.addDate() 參數 date 為空或長度不為 10 或日期不存在"); } int intYY = 0; int intMM = 0; int intDD = 0; //取得傳入日期之年月日(DB2之日期格式為yyyy-MM-dd) intYY = Integer.parseInt(date.substring(0, 4)); intMM = Integer.parseInt(date.substring(5, 7)); intDD = Integer.parseInt(date.substring(8, 10)); Calendar cal = Calendar.getInstance(); cal.set(intYY, intMM - 1, intDD); //進行年的運算 if (year != 0) { cal.add(Calendar.YEAR, year); } //進行月的運算 if (month != 0) { cal.add(Calendar.MONTH, month); } //進行日的運算 if (day != 0) { cal.add(Calendar.DATE, day); } //將運算過後的日期轉為DB2之日期格式 Date dDate = cal.getTime(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); return df.format(dDate); } /** * 判斷傳入日期是否介於某特定日期區間。 * @return true:介於特定日期間,false:未介於特定日期間。 * @param sInput 傳入之日期(西元年日期(YYYY-MM-DD))。 * @param sStart 起始之日期(西元年日期(YYYY-MM-DD))。 * @param sEnd 結束之日期(西元年日期(YYYY-MM-DD))。 */ public static boolean isBetween(String sInput, String sStart, String sEnd) { //DB2之日期格式為10碼 if (!isDate(sInput, false)) { throw new IllegalArgumentException("DATE.isBetween() 傳入之日期格式必須為yyyy-MM-dd"); } if (!isDate(sStart, false)) { throw new IllegalArgumentException("DATE.isBetween() 起始之日期格式必須為yyyy-MM-dd"); } if (!isDate(sEnd, false)) { throw new IllegalArgumentException("DATE.isBetween() 結束之日期格式必須為yyyy-MM-dd"); } boolean ret = false; int intYY = 0; int intMM = 0; int intDD = 0; Calendar cal = Calendar.getInstance(); //轉換輸入日期 intYY = Integer.parseInt(sInput.substring(0, 4)); intMM = Integer.parseInt(sInput.substring(5, 7)); intDD = Integer.parseInt(sInput.substring(8, 10)); cal.set(intYY, intMM - 1, intDD); Date dInput = cal.getTime(); //轉換起始日期 intYY = Integer.parseInt(sStart.substring(0, 4)); intMM = Integer.parseInt(sStart.substring(5, 7)); intDD = Integer.parseInt(sStart.substring(8, 10)); cal.set(intYY, intMM - 1, intDD); Date dStart = cal.getTime(); //轉換結束日期 intYY = Integer.parseInt(sEnd.substring(0, 4)); intMM = Integer.parseInt(sEnd.substring(5, 7)); intDD = Integer.parseInt(sEnd.substring(8, 10)); cal.set(intYY, intMM - 1, intDD); Date dEnd = cal.getTime(); if (dInput.compareTo(dStart) >= 0 && dInput.compareTo(dEnd) <= 0) { ret = true; } return ret; } /** * 檢查輸入字串是否為今日日期,以前面10碼做比對, * 只要前十碼格式為"yyyy-MM-dd"且為今日日期,回傳True * * @param date - 輸入日期 ex.2003-09-08或是TimeStamp * @return true - if input string represent today */ public static boolean isToday(String date) { boolean ret = false; if ((date == null) || date.equals("")) { throw new IllegalArgumentException("DATE.isToday() The input date is null or empty"); } SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); if (date.trim().length() > 10) { ret = f.format(new Date()).equals(date.substring(0, 10)); } else { ret = f.format(new Date()).equals(date); } return ret; } /** * 轉換DB格式的Date值 * ex.<br> * tranDateFormat("2003-3-3","-")回傳2003-03-03<br> * tranDateFormat("2003/3/3","/")回傳2003/03/03<br> * * @param date - input String * @param delimeter - '-','/','' * @return the Format String for date */ public static String tranDateFormat(String date, String delimeter) { if (date == null || date.length() < 1) { throw new IllegalArgumentException("DATE.tranDateFormat() The date is null"); } if (delimeter == null || delimeter.length() < 1) { throw new IllegalArgumentException("DATE.tranDateFormat() The delimeter is null"); } if (!isDateExist(date, false)) { throw new IllegalArgumentException("DATE.tranDateFormat() the date isnot exist"); } java.util.StringTokenizer stoken = new java.util.StringTokenizer(date, delimeter); int count = stoken.countTokens(); if (count != 3) { throw new IllegalArgumentException("DATE.tranDateFormat() The input format must be yyyy" + delimeter + "MM" + delimeter + "dd"); } //count = 3 String yyyy = stoken.nextToken(); String mm = stoken.nextToken(); String dd = stoken.nextToken(); StringBuffer sbf = new StringBuffer(); sbf.append(STRING.fillZero(yyyy, 4)).append("-").append(STRING.fillZero(mm, 2)).append("-").append(STRING.fillZero(dd, 2)); String chkDate = sbf.toString(); if (!isDate(chkDate, false)) { throw new IllegalArgumentException("DATE.tranDateFormat() The date is invalid."); } String retDate = STRING.fillZero(yyyy, 4) + delimeter + STRING.fillZero(mm, 2) + delimeter + STRING.fillZero(dd, 2); return retDate; } /** * 轉換DB格式的Date.ex.<br> * tranDateFormat("2003-3-3")回傳"2003-03-03" * @param date - input String * @return the yyyy-MM-dd Format String for date */ public static String tranDateFormat(String date) { return tranDateFormat(date, "-"); } /** * 取得目前時間的Date值 ex.'2003-09-08' * @return currentdate string with pattern "yyyy-MM-dd" */ public static String getDBDate() { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd"); return f.format(new Date()); } /** * 取得DB格式的Date值 ex.'2003-09-08'<br> * 若傳入20030303回傳2003-03-03<br> * 若傳入2003:03:03回傳2003-03-03 其中':'為任何分隔字元<br> * @param date - input String * @return the DBFormat String for date */ public static String getDBDate(String date) { if ((date == null) || (date.equals(""))) { throw new IllegalArgumentException("DATE.getDBDate() the parameter is empty"); } if (!isDateExist(date, false)) { throw new IllegalArgumentException("DATE.getDBDate() the date isnot exist"); } String ret = null; if (date.length() == 8) { StringBuffer sbf = new StringBuffer(); if (date.indexOf("-") >= 0) { sbf.append(date.substring(0, 4)).append("-0").append(date.substring(5, 6)).append("-0").append(date.substring(7)); } else { sbf.append(date.substring(0, 4)).append("-").append(date.substring(4, 6)).append("-").append(date.substring(6)); } ret = sbf.toString(); } else if (date.length() == 9) { StringTokenizer st = new StringTokenizer(date, "-"); ret = ""; while (st.hasMoreTokens()) { String temp = st.nextToken(); if (!ret.equals("")) { if (temp.length() == 1) { ret = ret + "-0" + temp; } else { ret = ret + "-" + temp; } } else { ret = temp; } } } else if (date.length() == 10) { ret = date.substring(0, 4) + "-" + date.substring(5, 7) + "-" + date.substring(8); } else { throw new IllegalArgumentException("DATE.getDBDate() the parameter.length() must equal 8 or 10"); } return ret; } /** * 取得目前時間的Time值ex. '15.15.15' * @return currenttime string */ public static String getDBTime() { SimpleDateFormat f = new SimpleDateFormat("HH.mm.ss"); return f.format(new Date()); } /** * 取得DB格式的Time值 ex.'16.15.14'<br> * 若傳入161514回傳16.15.14<br> * 若傳入16:15:14回傳16.15.14<br> * @return currenttime string */ public static String getDBTime(String time) { if ((time == null) || (time.equals(""))) { throw new IllegalArgumentException("DATE.getDBTime() the parameter is empty"); } String ret = null; if (time.length() == 6) { StringBuffer sbf = new StringBuffer(); sbf.append(time.substring(0, 2)).append(".").append(time.substring(2, 4)).append(".").append(time.substring(4)); ret = sbf.toString(); } else if (time.length() == 8) { StringBuffer sbf = new StringBuffer(); sbf.append(time.substring(0, 2)).append(".").append(time.substring(3, 5)).append(".").append(time.substring(6)); ret = sbf.toString(); } else { throw new IllegalArgumentException("DATE.getDBTime() the parameter.length() must equal 6 or 8"); } return ret; } /** * 取得目前時間的TimeStamp 使用pattern "yyyy-MM-dd-HH.mm.ss.SSS000"<br> * ex.'2003-09-08-17.12.30.000000' <br> * @return current timestame string of pattern "yyyy-MM-dd-HH.mm.ss.SSS000" */ public static String getDBTimeStamp() { SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss.SSS000"); return f.format(new Date()); } /** * 轉換輸入字串為db2的timestamp格式,輸入類型分成兩大類, * <br>1.yyyyMMddHHmmss 此類沒有區隔符號的 * <br>2.yyyy-MM-dd HH:mm:ss.fffffffff 或 yyyy-MM-dd-HH.mm.ss * <br> * 區分出這兩類後若類別為1長度介於8-13則當成長度8處理,之後的<b>時間會採目前時間</b>, * 類別為1長度大於等於14則當成長度14處理。<br> * 若類別為2長度介於10-18則當成長度10處理,之後的<b>時間會採目前時間</b>, * 類別為2長度大於等於19則當成長度19處理。23,26特別處理。<br> * * 範例: * <table> * <tr> * <td>傳入</td><td>回傳</td> * <td>20030908</td><td>2003-09-08-HH.mm.ss.000000</td> * <td>2003-09-08</td><td>2003-09-08-HH.mm.ss.000000</td> * <td>20030908010203</td><td>2003-09-08-01.02.03.000000</td> * <td>2003-09-08-01.02.03</td><td>2003-09-08-01.02.03.000000</td> * <td>2003-09-08-01.02.03.1</td><td>2003-09-08-01.02.03.000000</td> * <td>2003-09-08 01:02:03</td><td>2003-09-08-01.02.03.000000</td> * <td>2003-09-08 01:02:03.123</td><td>2003-09-08 01.02.03.123</td> * <td>2003-09-08 01:02:03.123456</td><td>2003-09-08 01.02.03.123456</td> * </tr> * </table> * @param date - 西元年ex.2003-09-08 * @return timestamp ex.2003-09-08 19.01.30.000000 */ public static String getDBTimeStamp(String date) { return getDBTimeStamp(date, false); } /** * 轉換輸入字串為db2的timestamp格式,輸入類型分成兩大類, * <br>1.yyyyMMddHHmmss 此類沒有區隔符號的 * <br>2.yyyy-MM-dd HH:mm:ss.fffffffff 或 yyyy-MM-dd-HH.mm.ss * <br> * 區分出這兩類後若類別為1長度介於8-13則當成長度8處理,之後的<b>時間會補0</b>, * 類別為1長度大於等於14則當成長度14處理。<br> * 若類別為2長度介於10-18則當成長度10處理,之後的<b>時間會補0</b>, * 類別為2長度大於等於19則當成長度19處理。23,26特別處理。<br> * * 範例: * assertEquals("2003-10-10 00.00.00.000000",DATE.getDBTimeStampPadZero("2003-10-10"));<br> * assertEquals("2003-10-10 10.10.10.000000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10"));<br> * assertEquals("2003-10-10 10.10.10.000000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10."));<br> * assertEquals("2003-10-10-10.10.10.100000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10.1"));<br> * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10.00"));<br> * assertEquals("2003-10-10-10.10.10.123000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10.123"));<br> * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10.0000"));<br> * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10.00000"));<br> * assertEquals("2003-10-10-10.10.10.123456",DATE.getDBTimeStampPadZero("2003-10-10 10:10:10.123456"));<br> * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStampPadZero("2003-10-10-10.10.10.000000sdfdsfsdfg"));<br> * * @param date - 西元年ex.2003-09-08 * @return timestamp ex.2003-09-08-19.01.30.000000 */ public static String getDBTimeStampPadZero(String date) { return getDBTimeStamp(date, true); } /** * <pre> * 轉換輸入字串為db2的timestamp格式,輸入類型分成兩大類, * 1.yyyyMMddHHmmss 此類沒有區隔符號的 * 2.yyyy-MM-dd HH:mm:ss.fffffffff 或 yyyy-MM-dd-HH.mm.ss * * 區分出這兩類後若類別為1長度介於8-13則當成長度8處理, * 類別為1長度大於等於14則當成長度14處理。 * 若類別為2長度介於10-18則當成長度10處理, * 類別為2長度大於等於19則當成長度19處理。23,26特別處理。 * * 範例: * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStamp("2003-10-10-10.10.10")); * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStamp("2003-10-10-10.10.10.")); * assertEquals("2003-10-10-10.10.10.1",DATE.getDBTimeStamp("2003-10-10-10.10.10.1")); * assertEquals("2003-10-10-10.10.10.00",DATE.getDBTimeStamp("2003-10-10-10.10.10.00")); * assertEquals("2003-10-10-10.10.10.123",DATE.getDBTimeStamp("2003-10-10-10.10.10.123")); * assertEquals("2003-10-10-10.10.10.0000",DATE.getDBTimeStamp("2003-10-10-10.10.10.0000")); * assertEquals("2003-10-10-10.10.10.123456",DATE.getDBTimeStamp("2003-10-10-10.10.10.123456")); * assertEquals("2003-10-10-10.10.10.000000",DATE.getDBTimeStamp("2003-10-10-10.10.10.000000sdfdsfsdfg")); * </pre> * @param date - 西元年ex.2003-09-08 * @param isPaddingZero - 不足的時間是否補0 ex. HH.mm.ss/00.00.00 * @return timestamp ex.2003-09-08-19.01.30.000000 */ private static String getDBTimeStamp(String date, boolean isPaddingZero) { String ret = null; String subTimeStamp = null; if (DATE.isDBTimeStamp(date, false)) { return date; } if (isPaddingZero) { subTimeStamp = "-00.00.00.000000"; } else { SimpleDateFormat f = new SimpleDateFormat("-HH.mm.ss.000000"); subTimeStamp = f.format(new Date()); } if ((date == null) || (date.equals(""))) { throw new IllegalArgumentException("DATE.getDBTimeStamp() the parameter is empty"); } if (Character.isDigit(date.charAt(4))) { //type with no delimiter if (date.length() < 8) { throw new IllegalArgumentException("DATE.getDBTimeStamp() 格式應為yyyyMMdd"); } if (date.length() == 8) { String tmp = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6); ret = tmp.concat(subTimeStamp); } else if ((date.length() > 8) && (date.length() < 14)) { String tmp = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8); ret = tmp.concat(subTimeStamp); } else if (date.length() == 14) { ret = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + "-" + date.substring(8, 10) + "." + date.substring(10, 12) + "." + date.substring(12) + ".000000"; } else if (date.length() > 14) { ret = date.substring(0, 4) + "-" + date.substring(4, 6) + "-" + date.substring(6, 8) + "-" + date.substring(8, 10) + "." + date.substring(10, 12) + "." + date.substring(12, 14) + ".000000"; } } else { //type with delimiter if (date.length() < 10) { throw new IllegalArgumentException("DATE.getDBTimeStamp() the length is not correct length < 10"); } if (date.length() == 10) { String tmp = date; ret = tmp.concat(subTimeStamp); } else if ((date.length() > 10) && (date.length() < 19)) { String tmp = date.substring(0, 10); ret = tmp.concat(subTimeStamp); } else if (date.length() == 19 || date.length() == 20) { ret = date.substring(0, 4) + "-" + date.substring(5, 7) + "-" + date.substring(8, 10) + "-" + date.substring(11, 13) + "." + date.substring(14, 16) + "." + date.substring(17, 19) + ".000000"; } else if (date.length() > 20) { ret = date.substring(0, 4) + "-" + date.substring(5, 7) + "-" + date.substring(8, 10) + "-" + date.substring(11, 13) + "." + date.substring(14, 16) + "." + date.substring(17, 19) + "."; int count = 6 - date.substring(20).length(); if (count <= 0) { ret += date.substring(20, 26); } else { if (isPaddingZero) { String zero = ""; for (int i = 0; i < count; i++) { zero += "0"; } ret += date.substring(20) + zero; } else { ret += date.substring(20); } } } } return ret; } /** * 轉換任意兩種日期格式。 * * @param date 欲被轉換的日期字串。 * @param fromFormat 原日期格式pattern(ex: "yyyy/MM/dd")。 * @param toFormat 轉換後的日期格式pattern(ex: "yyyy-MM-dd"")。 */ public static String toDateFormat(String date, String fromFormat, String toFormat) throws java.text.ParseException { if (date == null || date.length() < 1) { throw new IllegalArgumentException("DATE.toDateFormat() 傳入日期date錯誤"); } String strOut = date; SimpleDateFormat dfFrom = new SimpleDateFormat(fromFormat); SimpleDateFormat dfTo = new SimpleDateFormat(toFormat); try { Date dateTemp = dfFrom.parse(date); strOut = dfTo.format(dateTemp); } catch (java.text.ParseException ex) { throw ex; } catch (Exception ex) { throw new java.text.ParseException(ex.getMessage(), 0); } return strOut; } /** * 轉換日期成yyyyMMdd格式 * input 格式為yyyyMMdd,yyyy/MM/dd,yyyy.MM.dd,yyyy-MM-dd,yyyy/M/d,yyyy-M-d * @param sdate 要轉換的日期 * */ public static String toDate_yyyyMMdd(String sdate) { StringBuffer ret = new StringBuffer(); if ((sdate == null) || (sdate.equals(""))) { throw new IllegalArgumentException("DATE.toDate_yyyyMMdd() 傳入參數為空值或null"); } if (!isDateExist(sdate, false)) { throw new IllegalArgumentException("DATE.toDate_yyyyMMdd() 日期不存在"); } sdate = sdate.trim(); int[] delimPos = new int[2]; int deliCount = 0; int len = sdate.length(); for (int i = 0; i < len; i++) { char ch = sdate.charAt(i); if (!Character.isDigit(ch)) { if (deliCount > 1) { throw new IllegalArgumentException("DATE.toDate_yyyyMMdd() 傳入參數不符合預期日期格式,分隔字元多於2個"); } delimPos[deliCount] = i; deliCount++; } } if (deliCount == 0) { if (sdate.length() == 8) { return sdate; } else { throw new IllegalArgumentException("DATE.toDate_yyyyMMdd() 傳入參數不符合預期日期格式。"); } } else { String yyyy = sdate.substring(0, delimPos[0]); String MM = sdate.substring(delimPos[0] + 1, delimPos[1]); String dd = sdate.substring(delimPos[1] + 1); if (MM.length() == 1) { MM = "0".concat(MM); } if (dd.length() == 1) { dd = "0".concat(dd); } ret.append(yyyy); ret.append(MM); ret.append(dd); if (ret.length() != 8) { throw new IllegalArgumentException("DATE.toDate_yyyyMMdd() 傳入參數不符合預期日期格式。"); } } return ret.toString(); } /** * 檢核輸入的日期是否正確,西元年會限制在 1931 以前(不含)。 * @param date 欲被轉換的日期字串,格式pattern("yyyy-MM-dd")。 * @return 若日期正確會回傳 true,不正確則回傳false。Note:傳入null或空字串或長度不為10結果為false。 */ public static boolean isDate(String date) { return isDate(date, true); } /** * 檢核輸入的日期是否正確。 * @param date 欲被轉換的日期字串,格式pattern("yyyy-MM-dd")。 * @param yearLimit 西元年是否限制在 1931 以前(不含) * @return 若日期正確會回傳 true,不正確則回傳false。Note:傳入null或空字串或長度不為10結果為false。 */ public static boolean isDate(String date, boolean yearLimit) { if ((date == null) || (date.length() != 10)) { return false; } if (!isDateExist(date, yearLimit)) { return false; } SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); boolean result = false; try { sf.parse(date); result = true; } catch (NumberFormatException numExp) { result = false; } catch (ParseException psExp) { result = false; } return result; } /** * * 檢查傳入字串是否符合pattern表示式之日期格式,西元年會限制在 1931 以前(不含)。<br> * 日期pattern請使用'#'表示數字<br> * pattern ex.####-##-##, ####/##/##,########,####__##__##<br> * * @param date 欲檢查的字串 * @param pattern 檢查date是否符合此pattern * @return */ public static boolean isDate(String date, String pattern) { return isDate(date, pattern, true); } /** * 檢查傳入字串是否符合pattern表示式之日期格式<br> * 日期pattern請使用'#'表示數字<br> * pattern ex.####-##-##, ####/##/##,########,####__##__##<br> * * @param date 欲檢查的字串 * @param pattern 檢查date是否符合此pattern * @param yearLimit 西元年是否限制在 1931 以前(不含) * @return 若日期正確會回傳 true,不正確則回傳false。Note:傳入null或空字串為false。 */ public static boolean isDate(String date, String pattern, boolean yearLimit) { boolean ret = true; if (isDateExist(date, yearLimit) && date.length() == pattern.length()) { for (int i = 0; i < date.length(); i++) { if (pattern.charAt(i) == '#') { if (!Character.isDigit(date.charAt(i))) { ret = false; break; } } else { if (date.charAt(i) != pattern.charAt(i)) { ret = false; break; } } } } else { ret = false; } return ret; } /** * 檢核輸入的日期時間是否正確,西元年會限制在 1931 以前(不含)。<br> * @param stamp 欲被檢核的日期字串,格式DB2 formate pattern("yyyy-MM-dd-HH.mm.ss.000") <br> * or pattern("yyyy-MM-dd HH:mm:ss.000000")。最後面的毫秒可為 0~6 位數 * @param yearLimit * @return 若日期正確會回傳 true,不正確則回傳false。Note:傳入null或空字串為false。 */ public static boolean isDBTimeStamp(String stamp) { return isDBTimeStamp(stamp, true); } /** * 檢核輸入的日期時間是否正確。 * * @param date 欲被檢核的日期字串,格式DB2 formate pattern("yyyy-MM-dd-HH.mm.ss.000") <br> * or pattern("yyyy-MM-dd HH:mm:ss.000000")。最後面的毫秒可為 0~6 位數 * @param yearLimit 西元年是否限制在 1931 以前(不含) * @return 若日期正確會回傳 true,不正確則回傳false。Note:傳入null或空字串為false。 */ public static boolean isDBTimeStamp(String stamp, boolean yearLimit) { if ((stamp == null) || (stamp.equals("")) || stamp.length() < 19) { return false; } String tmp = stamp.trim(); //檢查前10字串是否為為date格式 if (!isDateExist(tmp.substring(0, 10), yearLimit)) { return false; } if (tmp.length() < 19 || tmp.length() > 26) { return false; } try { // 先以 yyyy-mm-dd hh:mm:ss.000000 的格式檢查 java.sql.Timestamp.valueOf(stamp); return true; } catch (IllegalArgumentException illae) { String strTime = null; //檢查字串是否為符合 timestamp 的格式字元 if (!isDateString(stamp)) { return false; } if (tmp.length() == 19) { strTime = tmp.substring(11); } else { strTime = tmp.substring(11, tmp.lastIndexOf('.')).trim(); } if (strTime.length() != 8) { return false; } boolean result = false; try { int h = Integer.parseInt(strTime.substring(0, 2)); int m = Integer.parseInt(strTime.substring(3, 5)); int s = Integer.parseInt(strTime.substring(6, 8)); if (((h >= 0) && (h < 24)) && ((m >= 0) && (m < 60)) && ((s >= 0) && (s < 60))) { result = true; } } catch (NumberFormatException ne) { result = false; } return result; } } /** * 解析出連續數字組成字串陣列回傳 * ex * String[] item = parseNumber("2004 02/09-11_:12~13.000"); * item[0]="2004" * item[1]="02" * item[2]="09" * item[3]="11" * item[4]="12" * item[5]="13" * item[6]="000" * * @param str - String to parse * @return String[] the array contains serial number */ public static String[] parseNumber(String str) { ArrayList ret = new ArrayList(); int idx = 0; char ch; for (int i = 0; i < str.length(); i++) { ch = str.charAt(i); if (ch >= '0' && ch <= '9') { } else { if (i > idx) { ret.add(str.substring(idx, i)); } idx = i + 1; } //最後一筆記得要加入 if (i == str.length() - 1) { ret.add(str.substring(idx)); } } String[] retA = (String[]) ret.toArray(new String[ret.size()]); return retA; } /** * 檢查是否為日期字串格式,檢查每一個字元是否為數字0-9及'-', ':', '_', '/' * @param 要檢查的字串 * @return true */ private static boolean isDateString(String strDate) { //System.out.println("strDate: " + strDate); boolean ret = true; char ch = 0; int intCharNum = strDate.length(); for (int i = 0; i < intCharNum; i++) { ch = strDate.charAt(i); if ((ch >= '0' && ch <= '9') || (ch == '-') || (ch == ':') || (ch == '_') || (ch == '/') || (ch == '.')) { } else { ret = false; break; } } //System.out.println("ret: " + ret); return ret; } /** * 判斷日期是否存在,取出此字串中的三個數字部分計算年月日是否存在 <br> * ex.2003-12-01 比對2003 12 01 為true<br> * ex.2007/2/29 比對2007 2 29 為false (非閏年2月無29日)<br> * * @param date * @param yearLimit 西元年是否限制在 1931 以前(不含) * @return */ private static boolean isDateExist(String date, boolean yearLimit) { if (!isDateString(date)) { return false; } boolean isDate = false; int intYear = 0; int intMonth = 0; int intDay = 0; String[] items = parseNumber(date); try { if (items.length == 1 && date.length() == 8) { intYear = Integer.parseInt(date.substring(0, 4)); intMonth = Integer.parseInt(date.substring(4, 6)); intDay = Integer.parseInt(date.substring(6)); } else if (items.length == 3) { intYear = Integer.parseInt(items[0]); intMonth = Integer.parseInt(items[1]); intDay = Integer.parseInt(items[2]); } isDate = isDateExist(intYear, intMonth, intDay, yearLimit); } catch (NumberFormatException nume) { } return isDate; } /** * 判斷日期是否存在。 <br> * * @param intYear 西元年(yyyy) * @param intMonth 月 * @param intDay 日 * @param yearLimit 西元年是否限制在 1931 以前(不含) */ private static boolean isDateExist(int intYear, int intMonth, int intDay, boolean yearLimit) { int[] Month_day = GENERAL_MONTH_DAY; if (yearLimit && !otherCheckRoleByDate(intYear, intMonth, intDay)) { return false; } boolean isDate = false; if (isLeap(intYear)) { Month_day = LEAP_YEAR_MONTH_DAY; } if (intMonth > 0 && intMonth <= 12) { if (intDay > 0 && intDay <= Month_day[intMonth]) { //比對日期為正確日期 isDate = true; } } //System.out.println("isDate: " + isDate); return isDate; } /** * 其他檢核規則 *  1.西元 1931年以前(不含)及民國 20 年以前(不含)算是不正確之日期格式。 *  2.1911-01-01(民國 000101)視為合理日期。 * @param intYear * @param intMonth * @param intDay * @return */ private static boolean otherCheckRoleByDate(int intYear, int intMonth, int intDay) { // 申請書編號:100823000284 // 申請書內容:西元 1931年以前(不含)及民國 20 年以前(不含)算是不正確之日期格式 if (intYear < 1931) { // 1911-01-01 (民國前一年一月一日)視為合理日期。 if (intYear == 1911 && intMonth == 1 && intDay == 1) { return true; } return false; } return true; } /** * 取得當月份的第一天 yyyy-mm-01 * * @return 日期字串(格式:yyyy-mm-dd) */ public static String getMonthFirstDate() { String date = DATE.getDBDate(); date = date.substring(0, 8) + FIRST_DATE; return date; } /** * 取得傳入月份的第一天 yyyy-mm-01, <br> * EX: 傳入 2004-04-04 or 200404 回傳 2004-04-01<br> * * @param date yyyymm or yyyy-mm-dd * @return 日期字串(格式:yyyy-mm-dd) */ public static String getMonthFirstDate(String date) { if (date.length() == 10) return date.substring(0, 8) + FIRST_DATE; else if (date.length() == 6) return DATE.getYYYYMMDD(date); else return "DATE INPUT ERROR"; } /** * 以指定日期回傳上月底的日期 * * @param date yyyy-mm-dd or yyyymm * @return 日期字串(格式:yyyy-mm-dd) */ public static String getLastMonthLastDate(String date) { return DATE.addDate(getMonthFirstDate(date), 0, 0, -1); } /** * 以今天的日期為基準回傳上月底的日期 * * @return 日期字串(格式:yyyy-mm-dd) */ public static String getLastMonthLastDate() { return DATE.addDate(getMonthFirstDate(), 0, 0, -1); } /** * 以指定日期取得上個月的第一天 * * @param date yyyy-mm-dd or yyyymm * * @return 日期字串(格式:yyyy-mm-dd) */ public static String getLastMonthFirstDate(String date) { return DATE.addDate(getMonthFirstDate(date), 0, -1, 0); } /** * 以今天的日期為基準回傳上個月的第一天日期 * * @return 日期字串(格式:yyyy-mm-dd) */ public static String getLastMonthFirstDate() { return DATE.addDate(getMonthFirstDate(), 0, -1, 0); } /** * 以指定日期取得當月的最後一天 * * @param date yyyy-mm-dd or yyyymm * @return 日期字串(格式:yyyy-mm-dd) */ public static String getMonthLastDate(String date) { return DATE.addDate(getMonthFirstDate(date), 0, 1, -1); } /** * 以今天的日期為基準回傳當月最後一天 * * @return 日期字串(格式:yyyy-mm-dd) */ public static String getMonthLastDate() { return DATE.addDate(getMonthFirstDate(), 0, 1, -1); } /** * private method to transfer input date to the first date of the month * @param yyyymm - the date format only contains year and month */ private static String getYYYYMMDD(String yyyymm) { StringBuffer sbf = new StringBuffer(); sbf.append(yyyymm.substring(0, 4)).append("-").append(yyyymm.substring(4, 6)).append("-").append(FIRST_DATE); return sbf.toString(); } /** * 將西元年的 Timestamp 轉為民國年的 Timestamp * @param stamp - yyyy-mm-dd-hh.mm.ss.000000 或 yyyy-mm-dd hh:mm:ss.000000 * * @return yyy/mm/dd hh:mm:ss.000000 字串 * @throws 格式錯誤時拋出 IllegalArgumentException */ public static String toROCTimestamp(String stamp) { StringBuffer result = new StringBuffer(27); if (!DATE.isDBTimeStamp(stamp, false)) { throw new IllegalArgumentException(stamp + " 格式錯誤,必需為yyyy-mm-dd-hh.mm.ss.000000 或 yyyy-mm-dd hh:mm:ss.000000"); } String hours = stamp.substring(11); String Y2K = DATE.toROCFormat(stamp.substring(0, 10), "/"); result.append(Y2K); result.append(" "); result.append(hours); return result.toString(); } /** * 將民國年的 Timestamp 轉為西元年的 Timestamp * @param stamp - yyy/mm/dd hh.mm.ss.000000(頁面顯示的格式) * * @return yyyy-mm-dd hh:mm:ss.000000 字串 * @throws 格式錯誤時拋出 IllegalArgumentException */ public static String toY2KTimestamp(String stamp) throws Exception { StringBuffer result = new StringBuffer(27); int index = stamp.lastIndexOf("-"); if (index == -1) { index = stamp.indexOf(" "); if (index == -1) { throw new IllegalArgumentException("民國日期格式輸入錯誤"); } } String hours = stamp.substring(index + 1); String ROC = stamp.substring(0, index); String[] ss = STRING.split(ROC, "/"); for (int i = 0; i < ss.length; i++) { result.append(ss[i]); } ROC = DATE.toY2KDate(result.toString()); result.delete(0, result.length()); result.append(ROC); result.append(" "); result.append(hours); return result.toString(); } /** * 傳入西元 2004-01-01 或 民國 930101 ,取出西元年。 <br> * * @param strDate 日期 * * @return 西元年(yyyy) * * @throws IllegalArgumentException */ public static String getY2KYear(String strDate) throws IllegalArgumentException { if (strDate == null) { throw new IllegalArgumentException("輸入日期為 null !!!"); } strDate = strDate.trim(); if (!isDateString(strDate)) { throw new IllegalArgumentException("輸入日期格式錯誤: " + strDate); } String strY2KYear = "XXXX"; int intDateLen = strDate.length(); try { if (intDateLen == 6) { int intY2KYear = Integer.parseInt(strDate.substring(0, 2)) + 1911; strY2KYear = Integer.toString(intY2KYear); } else if (intDateLen == 7) { int intY2KYear = Integer.parseInt(strDate.substring(0, 3)) + 1911; strY2KYear = Integer.toString(intY2KYear); } else if (intDateLen == 10 && (strDate.charAt(4) == '-') && (strDate.charAt(7) == '-')) { strY2KYear = strDate.substring(0, 4); } else { throw new IllegalArgumentException("輸入日期格式錯誤: " + strDate); } } catch (NumberFormatException e) { throw new IllegalArgumentException("輸入日期格式錯誤: " + strDate); } return strY2KYear; } /** * 傳入西元 2004-01-01 或 民國 930101 ,取出民國年。 <br> * * @param strDate 日期 * @return 民國年(yy 或 yyy) * * @throws IllegalArgumentException */ public static String getROCYear(String strDate) throws IllegalArgumentException { if (strDate == null) { throw new IllegalArgumentException("輸入日期為 null !!!"); } strDate = strDate.trim(); if (!isDateString(strDate)) { throw new IllegalArgumentException("輸入日期格式錯誤: " + strDate); } String strROCYear = "XXX"; int intDateLen = strDate.length(); if (intDateLen == 6) { strROCYear = strDate.substring(0, 2); } else if (intDateLen == 7) { strROCYear = strDate.substring(0, 3); } else if (intDateLen == 10 && (strDate.charAt(4) == '-') && (strDate.charAt(7) == '-')) { try { int intROCYear = Integer.parseInt(strDate.substring(0, 4)) - 1911; strROCYear = Integer.toString(intROCYear); } catch (NumberFormatException e) { throw new IllegalArgumentException("輸入日期格式錯誤: " + strDate); } } else { throw new IllegalArgumentException("輸入日期格式錯誤: " + strDate); } return strROCYear; } /** * 將西元各別年、月、日 數字轉換成民國日期。 <br> * * @param intY2KYear 西元年 * @param intMonth 月 * @param intDay 日 * @return 民國日期 */ public static String toROCDate(int intY2KYear, int intMonth, int intDay) { if (!isDateExist(intY2KYear, intMonth, intDay, false)) { StringBuffer msg = new StringBuffer(); msg.append("輸入日期格式錯誤: ").append("\r\n"); msg.append("年: ").append(intY2KYear).append("\r\n"); msg.append("月: ").append(intMonth).append("\r\n"); msg.append("日: ").append(intDay).append("\r\n"); throw new IllegalArgumentException(msg.toString()); } int intROCYear = intY2KYear - 1911; StringBuffer sbDate = new StringBuffer(); sbDate.append(intROCYear); if (intMonth < 10) { sbDate.append("0"); } sbDate.append(intMonth); if (intDay < 10) { sbDate.append("0"); } sbDate.append(intDay); return sbDate.toString(); } /** * 將民國各別年、月、日 數字轉換成西元日期。 <br> * * @param intROCYear 民國年 * @param intMonth 月 * @param intDay 日 * @return */ public static String toY2KDate(int intROCYear, int intMonth, int intDay) { int intY2KYear = intROCYear + 1911; if (!isDateExist(intY2KYear, intMonth, intDay, false)) { StringBuffer msg = new StringBuffer(); msg.append("輸入日期格式錯誤: ").append("\r\n"); msg.append("年: ").append(intROCYear).append("\r\n"); msg.append("月: ").append(intMonth).append("\r\n"); msg.append("日: ").append(intDay).append("\r\n"); throw new IllegalArgumentException(msg.toString()); } StringBuffer sbDate = new StringBuffer(); sbDate.append(intY2KYear).append("-"); if (intMonth < 10) { sbDate.append("0"); } sbDate.append(intMonth).append("-"); if (intDay < 10) { sbDate.append("0"); } sbDate.append(intDay); return sbDate.toString(); } // getCal private static final Calendar getCal() { return Calendar.getInstance(); } /** * Get a java.sql.Date instance of today * * @return Date of current day * @since V1.01 */ public static final java.sql.Date today() { java.util.Date dt = new java.util.Date(); dt = clearTimeFields(dt); return new java.sql.Date(dt.getTime()); } /** * Get a java.sql.Timestamp instance of current time * * @param ifClearTimeField (是否要計算到時、分、秒)<br> * 若為 true 則回傳代表 YYYY-MM-DD 00:00:00 的 Timestamp * 若為 false 回傳代表目前的時間的 Timestamp * @return Timestamp of current time * @since V1.01 */ public static final Timestamp currentTime(boolean ifClearTimeField) { java.util.Date dt = new java.util.Date(); if (ifClearTimeField) { // clear hour, min, sec, minsec field dt = clearTimeFields(dt); } return new Timestamp(dt.getTime()); } /** * Get a java.sql.Timestamp instance of current time * * @return Timestamp of current time * @since V1.01 */ public static final Timestamp currentTime() { return currentTime(false); } // clearTimeFields private static final Date clearTimeFields(Date dt) { Calendar cal = getCal(); cal.clear(); cal.setTime(dt); // clear hour, min, sec, minsec field cal.set(Calendar.MILLISECOND, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.HOUR_OF_DAY, 0); dt = cal.getTime(); cal.clear(); return dt; } /** * Get Timestamp instance of Date * * @param dt - 要被轉換的 Date instance * @return a Timestamp (YYYY-MM-DD 00:00:00) * @since V1.01 */ public static final Timestamp dateToTimestamp(java.util.Date dt) { // clear hour, min, sec, minsec field dt = clearTimeFields(dt); return new Timestamp(dt.getTime()); } /** * <pre> * 比較兩個 Date 是否為同一天 * </pre> * @param dt1 * @param dt2 * @return true if the same */ public static final boolean isSameDate(java.util.Date dt1, java.util.Date dt2) { if (dt1 == null || dt2 == null) return false; return DateUtils.isSameDay(dt1, dt2); //return Math.abs(dt1.getTime() - dt2.getTime()) < 86400000; } /** * 是否為本日 * * @param dt1 * @return true if the same */ public static final boolean isToday(java.util.Date dt1) { if (dt1 == null) return false; return isSameDate(dt1, today()); } /** * Get Date instance of Timestamp(取得時間戳記所帶表的日期) * * @param aTs * @return a Timestamp */ public static final java.sql.Date timestampToDate(Timestamp aTs) { return new java.sql.Date(aTs.getTime()); } /** * 將日期 String type 轉為 Timestamp type * @param tsStr * @return */ public static final Timestamp toTimestamp(String tsStr) { try { return Timestamp.valueOf(tsStr); } catch (Exception e) { // null by default } try { String[] pn = parseNumber(tsStr); StringBuffer sbf = new StringBuffer(); // yyyy-MM-dd HH:mm:ss.fffffffff sbf.append(pn[0]).append("-").append(pn[1]).append("-").append(pn[2]); sbf.append(" ").append(pn[3]).append(":").append(pn[4]).append(":").append(pn[5]).append(".").append(pn[6]); String date = sbf.toString(); return Timestamp.valueOf(date); } catch (Exception e) { // null by default } return null; } /** * Get Date instance of Timestamp(取得時間戳記所帶表的日期) * * @param aTsStr * @return a Timestamp */ public static final java.sql.Date timestampToDate(String tsStr) { try { return new java.sql.Date(toTimestamp(tsStr).getTime()); } catch (Exception e) { // null by default } return null; } /** * Format to 'yyMMdd' format of R.O.C. calendar (將 Date 物件 format 成民國年的日期回傳) * * @param dtStr String date string or timestamp * @return formated date string */ public static final String formatToROCDate(String dtStr) { try { return formatToROCDate(java.sql.Date.valueOf(dtStr)); } catch (Exception e) { // "" dy default } try { return formatToROCDate(toTimestamp(dtStr)); } catch (Exception e) { // "" dy default } return ""; } /** * Format to 'yyMMdd' format of R.O.C. calendar (將 Date 物件 format 成民國年的日期回傳) * * @param dt a java.util.Date instance * @return formated date string */ public static final String formatToROCDate(java.util.Date dt) { try { Calendar cal = getCal(); cal.clear(); cal.setTime(dt); int year = (cal.get(Calendar.YEAR) - 1911); return year + ((cal.get(Calendar.MONTH) + 1 > 9) ? "" + (cal.get(Calendar.MONTH) + 1) : "0" + (cal.get(Calendar.MONTH) + 1)) + ((cal.get(Calendar.DATE) > 9) ? "" + cal.get(Calendar.DATE) : "0" + cal.get(Calendar.DATE)); } catch (Exception e) { logger.fatal("", e); // return "" by default } return ""; } /** * Parse 'yyMMdd' format of R.O.C. calendar to Date class instance<BR> * (將民國年的日期字串 parse 為 java.sql.Date 的物件) * * @param dtStr date string in 'yyMMdd' format * @return Date instance (若民國年字串格式錯誤則回傳 null) */ public static final java.sql.Date parseROCDate(String dtStr) { try { if (dtStr.indexOf("/") != -1) { dtStr = StringUtils.replace(dtStr, "/", ""); } dtStr = toY2KDate(dtStr); return java.sql.Date.valueOf(dtStr); } catch (Exception e) { // return null by default } return null; } /** * Parse 'yyMMdd' format of R.O.C. calendar to Timestamp class instance * (將民國年的日期字串 parse 為 java.sql.Timestamp 的物件) * * @param dtStr date string in 'yyMMdd' format * @return Timstamp instance(若民國年字串格式錯誤則回傳 null) */ public static final Timestamp parseROCDateToTimestamp(String dtStr) { Date date = parseROCDate(dtStr); if (date == null) return null; return new Timestamp(date.getTime()); } /** * 取出西元年字串中的年月<br> * YYYY-MM-DD --> YYYYMM * * @param strDate - 西元年 YYYY-MM-DD * @return YYYYMM 6碼西元年月 * * @author IBM Dev Team * @since V1.01 */ public static String getYearAndMonth(String strDate) { return DATE.toDate_yyyyMMdd(strDate).substring(0, 6); } /** * <pre> * 檢查日期是否為正確的民國年日期,民國年會限制在 20 年以前(不含)。 * </pre> * @param strDate - 0931010 或 931010 的民國年日期字串 * @param allowNull - date 參數是否可為 null 值 * @return true 若為正確的民國年日期 */ public static boolean isROCDate(String strDate, boolean allowNull) { return isROCDate(strDate, allowNull, true); } /** * 檢查日期是否為正確的民國年日期 * * @param strDate - 0931010 或 931010 的民國年日期字串 * @param allowNull - date 參數是否可為 null 值 * @param yearLimit 民國年會限制在 20 年以前(不含) * @return true 若為正確的民國年日期 * * @author IBM Dev Team * @since V1.01 */ public static boolean isROCDate(String strDate, boolean allowNull, boolean yearLimit) { if (allowNull && StringUtils.isBlank(strDate)) { return true; } if (!allowNull && StringUtils.isBlank(strDate)) { return false; } try { return DATE.isDate(DATE.toY2KDate(strDate), yearLimit); } catch (Exception e) { return false; } } /** * 取得西元年今天的年月(YYYYMM) * * @return YYYYMM 的字串(如200502) * * @author IBM Dev Team * @since V1.01 */ public static String getTodayYearAndMonth() { String date = DATE.getDBDate(); StringBuffer sbf = new StringBuffer(); sbf.append(date.substring(0, 4)).append(date.substring(5, 7)); return sbf.toString(); } /** * 將民國年月 轉換成 西元年月 ex: 9403 會轉換為 200503 * * @param ROCDate 民國年日期 (YYYMMDD) or (YYYMM) * @return 西元年月 (YYYYMM) * * @author IBM Dev Team * @since V1.01 */ public static String getY2KYearAndMonth(String ROCDate) { if (ROCDate == null || "".equals(ROCDate)) { throw new RuntimeException("輸入為空字串或null"); } String Y; String M; if (ROCDate.length() == 4 || ROCDate.length() == 6) { Y = ROCDate.substring(0, 2); M = ROCDate.substring(2, 4); } else if (ROCDate.length() == 5 || ROCDate.length() == 7) { Y = ROCDate.substring(0, 3); M = ROCDate.substring(3, 5); } else { throw new RuntimeException("輸入格式錯誤"); } int year = Integer.parseInt(Y) + 1911; String Y2K_YYYYMM = Integer.toString(year) + M; return Y2K_YYYYMM; } /** * 將西元年月轉換成民國年月 ex: 200505 會轉換為 9405 * * @param Y2KDate 西元年日期 (YYYYMMDD) or (YYYYMM) * @return 民國年年月 (YYMM or YYYMM) * * @author IBM Dev Team * @since V1.01 */ public static String getROCYearAndMonth(String Y2KDate) { if (Y2KDate == null || "".equals(Y2KDate)) { throw new RuntimeException("輸入為空字串或null"); } String Y; String M; if (Y2KDate.length() == 6 || Y2KDate.length() == 8) { Y = Y2KDate.substring(0, 4); M = Y2KDate.substring(4, 6); } else { throw new RuntimeException("輸入格式錯誤"); } int year = Integer.parseInt(Y) - 1911; String ROC_YYYMM = Integer.toString(year) + M; return ROC_YYYMM; } /** * 將「西元年月-1」(一年以13個月計) * * ex:</br> * 200406 回傳 200405</br> * 200401 回傳 200313</br> * * @param Y2KDate * @return 西元年月 YYYYMM * * @author IBM Dev Team * @since V1.01 */ public static String getY2KminusOne(String Y2KDate) { if (Y2KDate.length() != 6) { throw new RuntimeException("輸入格式錯誤"); } String wkym; String year = Y2KDate.substring(0, 4); String month = Y2KDate.substring(4, 6); int m = Integer.parseInt(month); if (m == 1) { int y = Integer.parseInt(year, 10) - 1; wkym = Integer.toString(y) + "13"; } else { String mon = String.valueOf(m - 1); if (m < 11) { mon = "0" + mon; } wkym = year + mon; } return wkym; } /** * 將「西元年月+ 1」(一年以13個月計),當月份超過 13 時會加一年。</br> * ex:</br> * 200406 回傳 200407</br> * 200413 回傳 200501</br> * * @param Y2KDate * @return 西元年月 YYYYMM * * @author IBM Dev Team * @since V1.01 */ public static String getY2KplusOne(String Y2KDate) { if (Y2KDate.length() != 6) { throw new RuntimeException("輸入格式錯誤"); } String wkym; String year = Y2KDate.substring(0, 4); String month = Y2KDate.substring(4, 6); int m = Integer.parseInt(month); if (Integer.parseInt(month) == 13) { int y = Integer.parseInt(year) + 1; wkym = Integer.toString(y) + "01"; } else { String mon = String.valueOf(m + 1); if (m < 9) { mon = "0" + mon; } wkym = year + mon; } return wkym; } /** * 傳入西元年 , 回傳星期幾 , 日期需符合 yyyy-mm-dd 的格式 * @param inputDate * @return */ public static String getDATE_OF_WEEK(String inputDate) { if (!isDate(inputDate, false)) { logger.fatal("傳入日期有誤 , 傳入日期 = " + inputDate); throw new IllegalArgumentException("傳入日期有誤 , 傳入日期 = " + inputDate); } return getDATE_OF_WEEK(inputDate, "-"); } /** * 傳入西元年 , 分隔符號 , 回傳星期幾 , 不作日期格式的檢查 * @param inputDate * @param separator * @return */ public static String getDATE_OF_WEEK(String inputDate, String separator) { // if (!isDate(inputDate)) { // // logger.fatal("傳入日期有誤 , 傳入日期 = " + inputDate); // // //return ""; // throw new IllegalArgumentException("傳入日期有誤 , 傳入日期 = " + inputDate); // // } try { String dateArray[] = StringUtils.split(inputDate, separator); int year = Integer.parseInt(dateArray[0]); int month = Integer.parseInt(dateArray[1]) - 1; int date = Integer.parseInt(dateArray[2]); Calendar calendar = new GregorianCalendar(year, month, date); int index = ArrayUtils.indexOf(DATE_OF_WEEK_ARRAY, calendar.get(Calendar.DAY_OF_WEEK)); return DATE_OF_WEEK_CONVER[index]; } catch (Exception e) { logger.fatal("取出星期幾異常 , 傳入日期 = " + inputDate + " , 分隔符號 = " + separator, e); throw new IllegalArgumentException("取出星期幾異常 , 傳入日期 = " + inputDate + " , 分隔符號 = " + separator + " : " + e.getMessage()); } } /** * <pre> * 傳入西元年月日,回傳民國年中文日期 * ex: * 2006-12-01 回傳 九十五年十二月一日 * 2010-09-09 回傳 九十九年九月九日 * </pre> * * @param inputDate 西元年月日 ( ex : 2007-12-01) * @return 民國年中文日期 */ public static String toROC_C_Date(String inputDate) { if (!isDate(inputDate, false)) { throw new IllegalArgumentException("傳入日期有誤 , 傳入日期 = " + inputDate); } String[] Y2KDate = parseNumber(inputDate); //民國年、月、日 String ROC_YY = String.valueOf(Integer.parseInt(Y2KDate[0]) - 1911); String ROC_MM = Y2KDate[1]; String ROC_DD = Y2KDate[2]; StringBuffer sbf = new StringBuffer(); sbf.append(getCNum(ROC_YY)).append(aryROCUnits[2]).append(getCNum(ROC_MM)).append(aryROCUnits[3]).append(getCNum(ROC_DD)).append( aryROCUnits[4]); return sbf.toString(); } /** * 取得中文數字 * @param num * @return */ public static String getCNum(String num) { if (!STRING.isNumeric(num)) { throw new IllegalArgumentException("傳入數值有誤 , 傳入數值 = " + num); } int n = Integer.parseInt(num); String cNum = ""; if (n <= 10) { cNum = n == 10 ? aryROCUnits[0] : aryROCNumber[n]; } else if (n <= 99) { int stn1 = Integer.parseInt(num.substring(0, 1)); int stn2 = Integer.parseInt(num.substring(1, 2)); if (stn1 == 1) { cNum = aryROCUnits[0] + aryROCNumber[stn2]; } else { cNum = aryROCNumber[stn1] + aryROCUnits[0] + aryROCNumber[stn2]; } } else { int stn1 = Integer.parseInt(num.substring(0, 1)); int stn2 = Integer.parseInt(num.substring(1, 2)); int stn3 = Integer.parseInt(num.substring(2, 3)); cNum = aryROCNumber[stn1] + aryROCUnits[1]; if (stn2 > 0) { cNum += aryROCNumber[stn2] + aryROCUnits[0] + aryROCNumber[stn3]; } else if (stn3 > 0) { cNum += aryROCNumber[10] + aryROCNumber[stn3]; } } return cNum; } /** * <pre> * 檢核傳入日期是否在其指定區間天數之內(以執行日期為區間的基準日期) *   回傳值 < 0 時,表示傳入日期差距( 執行日期 + 區間起始天數 )之天數 *   回傳值 = 0 時,表示傳入日期落在( 執行日期 + 區間起始天數 )~( 執行日期 + 區間結束天數)之間 *   回傳值 > 0 時,表示傳入日期差距( 執行日期 + 區間結束天數 )之天數 * ex: * 假設執行日期為 2010-07-10 *    checkDate("2010-07-01", 0, 10) 「基準日期:2010-07-10;判斷區間為 2010-07-10 ~ 2010-07-20」,回傳 -9 (傳入日期 2010-07-01 < 區間起日 2010-07-10)。 *    checkDate("2010-07-01", -10, 10)「基準日期:2010-07-10;判斷區間為 2010-06-21 ~ 2010-07-20」,回傳 0 (區間起日 2010-06-21 <= 傳入日期 2010-07-01 <= 區間迄日 2010-07-20)。 *    checkDate("2010-07-20", -10, 10)「基準日期:2010-07-10;判斷區間為 2010-06-21 ~ 2010-07-20」,回傳 0 (區間起日 2010-06-21 <= 傳入日期 2010-07-01 <= 區間迄日 2010-07-20)。 *    checkDate("2010-07-21", -10, 10)「基準日期:2010-07-10;判斷區間為 2010-06-21 ~ 2010-07-20」,回傳 1 (傳入日期 2010-07-21 > 區間迄日 2010-07-20)。 * 假設執行日期為 2010-09-30 *    checkDate("2010-09-30", 5, 6) 「基準日期:2010-09-30;判斷區間為 2010-10-05 ~ 2010-10-06」,回傳 -5 (傳入日期 2010-09-30 < 區間起日 2010-10-05)。 * </pre> * @param inputDate * @param beginDays 區間起始天數 * @param endDays 區間結束天數 * @return */ public static int checkDate(String inputDate, int beginDays, int endDays) { if (!isDate(inputDate, false)) { throw new IllegalArgumentException("傳入日期有誤 ,傳入日期 = " + inputDate); } if (beginDays > endDays) { throw new IllegalArgumentException("傳入起始天數大於結束天數,起始天數 = " + beginDays + "、結束天數 = " + endDays); } String currentDate = getDBDate(); String beginDate = DATE.addDate(currentDate, 0, 0, beginDays); int diffDays_begin = DATE.diffDay(beginDate, inputDate); if (diffDays_begin < 0) { return diffDays_begin; } String endDate = DATE.addDate(currentDate, 0, 0, endDays); int diffDays_end = DATE.diffDay(endDate, inputDate); if (diffDays_end > 0) { return diffDays_end; } return 0; } /** * <pre> * 計算兩日期之間相差的年月日。 * ex: * 2012、2016 為閏年 * DATE.diffDay_YYMMDD("2012-01-01", "2013-03-20"),return Integer[0]=1, Integer[1]=2, Integer[2]=19 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2013-01-11", "2013-02-01"),return Integer[0]=0, Integer[1]=0, Integer[2]=21 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2013-02-28", "2013-03-01"),return Integer[0]=0, Integer[1]=0, Integer[2]=1 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2012-02-29", "2013-03-01"),return Integer[0]=1, Integer[1]=0, Integer[2]=1 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2012-03-10", "2013-03-07"),return Integer[0]=0, Integer[1]=11, Integer[2]=28 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2012-02-29", "2013-02-28"),return Integer[0]=1, Integer[1]=0, Integer[2]=0 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2012-02-28", "2013-02-28"),return Integer[0]=1, Integer[1]=0, Integer[2]=1 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2012-02-28", "2012-03-01"),return Integer[0]=0, Integer[1]=0, Integer[2]=2 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2013-02-28", "2013-03-01"),return Integer[0]=0, Integer[1]=0, Integer[2]=1 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2012-02-29", "2016-02-29"),return Integer[0]=4, Integer[1]=0, Integer[2]=0 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2013-02-28", "2016-02-29"),return Integer[0]=3, Integer[1]=0, Integer[2]=0 * --------------------------------------------------------------------------------------------------------- * DATE.diffDay_YYMMDD("2013-02-28", "2016-02-28"),return Integer[0]=2, Integer[1]=11, Integer[2]=28 * </pre> * @param startDate * @param endDate * @return */ public static Integer[] diffDay_YYMMDD(String startDate, String endDate) { if (!isDate(startDate) || !isDate(endDate)) { throw new IllegalArgumentException("傳入起日或迄日之日期格式有誤"); } return diffDay_YYMMDD(java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate)); } /** * <pre> * 計算兩日期之間相差年月日。 * 當所傳入的 java.util.Date 若是包含時間(如:new java.util.Date()),則會一併納入時間進行比較,例如: * 2013-09-25 與 2013-09-25 比較時,相差 0 天 * 2013-09-25 15:00:00 與 2013-09-25 比較時,則會變為相差 1 天 * </pre> * @param startDate * @param endDate * @return */ public static Integer[] diffDay_YYMMDD(Date startDate, Date endDate) { int diffDays = diffDay(startDate, endDate); if (diffDays < 0) { throw new IllegalArgumentException("傳入迄日需大於起日"); } if (diffDays == 0) { return new Integer[] { 0, 0, 0 }; } Calendar calendar = Calendar.getInstance(); calendar.setTime(startDate); int beginYear = calendar.get(Calendar.YEAR); int beginMonth = calendar.get(Calendar.MONTH) + 1; int beginDay = calendar.get(Calendar.DAY_OF_MONTH); calendar.setTime(endDate); int endYear = calendar.get(Calendar.YEAR); int endMonth = calendar.get(Calendar.MONTH) + 1; int endDay = calendar.get(Calendar.DAY_OF_MONTH); // 傳入的二個日期,當月份為二月時,判斷是否皆為該年度的最後一天 boolean februaryLastDayIsLeap; boolean beginLeapYearIsAddOneDiffDay; boolean endLeapYearIsSubOneDiffDay; if (beginMonth == 2 && endMonth == 2) { // 當傳入的月份為二月時,需判斷該年度是否為閏年 boolean beginIsLeap = isLeap(beginYear); boolean endIsLeap = isLeap(endYear); boolean februaryLastDay_begin = (beginIsLeap && beginDay == 29) || (!beginIsLeap && beginDay == 28); boolean februaryLastDay_end = (endIsLeap && endDay == 29) || (!endIsLeap && endDay == 28); februaryLastDayIsLeap = februaryLastDay_begin && februaryLastDay_end; beginLeapYearIsAddOneDiffDay = beginIsLeap; endLeapYearIsSubOneDiffDay = endIsLeap; } else { februaryLastDayIsLeap = false; beginLeapYearIsAddOneDiffDay = false; endLeapYearIsSubOneDiffDay = false; } int diffYear = endYear - beginYear; int diffMonth; int diffDay; if (februaryLastDayIsLeap) { diffMonth = 0; diffDay = 0; } else { diffMonth = endMonth - beginMonth; diffDay = endDay - beginDay; // 起啟日期為閏年二月時,差異天數需多加 1 天 if (beginLeapYearIsAddOneDiffDay) { diffDay++; } // 結束日期為閏年二月時,差異天數需多減 1 天 if (endLeapYearIsSubOneDiffDay) { diffDay--; } if (diffDay < 0) { String tempdate = DATE.getMonthLastDate(startDate.toString()); diffDay += Integer.parseInt(tempdate.substring(tempdate.length() - 2)); diffMonth--; // 當天數不足時,在傳入結束日期為閏年且二月的狀況,需再將被減掉的天數加回 if (endLeapYearIsSubOneDiffDay) { diffDay++; } } if (diffMonth < 0) { diffMonth += 12; diffYear--; } } return new Integer[] { diffYear, diffMonth, diffDay }; } // test method // public static void main(String[] argvs) { // // int days = checkDate("2010-09-30", 5, 6); // System.err.println(days); // // /* // String testDate = "1930-08-30"; // String testTimeStamp = "1930-08-30 11:21:00"; // String testROCDate = "190830"; // */ // String testDate = "1911-01-01"; // String testTimeStamp = "1911-01-01 11:21:00"; // String testROCDate = "000101"; // // System.err.println("DATE.isDate = " + isDate(testDate)); // System.err.println("DATE.isDate not year Limmit = " + isDate(testDate, false)); // // System.err.println(); // System.err.println("DATE.isDBTimeStamp = " + isDBTimeStamp(testTimeStamp)); // System.err.println("DATE.isDBTimeStamp not year Limmit = " + isDBTimeStamp(testTimeStamp, false)); // // System.err.println(); // System.err.println("DATE.isDate pattern = " + isDate(testDate, "####-##-##")); // System.err.println("DATE.isDate pattern not year Limmit= " + isDate(testDate, "####-##-##", false)); // // System.err.println(); // System.err.println("DATE.isROCDate pattern = " + isROCDate(testROCDate, false)); // System.err.println("DATE.isROCDate pattern not year Limmit = " + isROCDate(testROCDate, false, false)); // // System.err.println(); // System.err.println("DATE.toROC_C_Date = " + toROC_C_Date(testDate)); // // System.err.println(); // System.err.println("DATE.toY2KDate = " + toY2KDate(testROCDate)); // // System.err.println(); // System.err.println("DATE.tranDateFormat = " + tranDateFormat(testDate, "-")); // // System.err.println(); // System.err.println("DATE.toTimestamp = " + toTimestamp(testTimeStamp)); // // System.err.println(); // System.err.println("DATE.toROCDate = " + toROCDate(testDate)); // // System.err.println(); // System.err.println("DATE.diffDay = " + diffDay("1930-08-30", "1930-08-01")); // System.err.println("DATE.diffDay = " + diffDay("2010-08-30", "2010-09-02")); // // System.err.println(); // System.err.println("DATE.getDATE_OF_WEEK = " + getDATE_OF_WEEK("2010-08-30")); // // Timestamp d1 = Timestamp.valueOf("2005-03-23 14:19:07.265"); // Timestamp d2 = Timestamp.valueOf("2005-03-23 14:19:09.266"); // // System.err.println("d1 = " + d1 + "\t\t d1 = " + d2); // System.err.println("d1- d2 = " + (d1.getTime() - d2.getTime())); // // System.err.println("isSameDate = " + isSameDate(d1, d2)); // // System.err.println("中文日期 = " + toROC_C_Date("2022-12-10")); // System.err.println("中文數字 = " + getCNum("101")); // // System.err.println("checkDate = " + checkDate("2010-09-06", 1, 2)); // // } }