由輸入資料取得資訊、相依日期
由日期字串,解析後取得部分或相依資訊。若輸入字串無法通過parse解析為Java LocalDate物件,抛出執行期例外。
◎ int getYyy(input)
* 適用於:**YYYMMDD, YYYMM, YYY**
* 以數值格式取得民國年份,民國前一年(1911)的值為-1。
◎ int getMm(input)
* 適用於:**YYYMMDD, YYYMM**
* 以數值格式取得月份。
◎ int getDd(input)
* 適用於:**YYYMMDD**
* 以數值格式取得日。
◎ String toYYYMM(input)
* 適用於:**YYYMMDD**
* '年月日'轉換為'年月'格式
◎ String toYYY(input)
* 適用於:**YYYMMDD**
* '年月日'、'年月'轉換為'年'格式
◎ LocalDate firstDay(yyymm) / firstDay(yyymm,days)
* 適用於:**YYYMM**
* 取得當月的第N天。
◎ LocalDate lastDay(yyymm) / lastDay(yyymm,days)
* 適用於:**YYYMM**
* 取得當月的倒數第N天。
◎ String relativeDate (yyymmdd, ChronoUnit, amount)
- 適用於:YYYMMDD
- 取得相對日期的表示字串
- 時間單位使用JDK8的ChronoUnit
◎ String previousDate
◎ String nextDate
- 適用於:YYYMMDD
- 取得前一日/後一日的表示字串
◎ String previousMonth
◎ String nextMonth
- 適用於:YYYMM
- 取得後一月/後一月的表示字串
日期計數
- 原則上建議先檢查輸入,要求 day1 ≦ day2,對於一般使用邏輯而言,可能較為容易轉換概念。
- 這樣一來,大部分應用就可以把回傳值小於 0 (day1 > day2) 視作輸入錯誤。
- 當 day1 ≦ day2 時,回傳值大於 0
- 計數區段為:[day1 00:00 ~ day2 24:00]
- 例如計算出境日數,xxx/03/01 出發 ~ xxx/03/01 當日返程就算一天。
- 例如計算薪資日數,也是頭尾都算。
- 計數區段為:[day1 00:00 ~ day2 24:00]
當 day1 > day2 時,回傳值小於 0
- 計數區段為:[day2 00:00 ~ day1 00:00]
- 例如:繳費截止日 xxx/03/20,xxx/03/21 繳費為延遲一日(-1)
- countDays(date, deadline)
- 計數區段為:[day2 00:00 ~ day1 00:00]
回傳值永不為 0。
◎ long countDays(day1,day2)
* 適用於:**YYYMMDD**
* 計算涵蓋日數。
* start/stop 同日為 1 、stop 晚於 start 一日為 2 。
* stop 早於 start 一日為-1… 也就是 回傳值永不為 0
* 大部分應用可以把回傳值小於0 (stop<start) 視作輸入錯誤。
* 與一般Utility、Period.between的邏輯略有不同。
``` java
@Test
public void testCountDaysByString() {
// 前一日:980803~980802
assertEquals(-1, YYYMMDDUtils.countDays("0980803", "0980802"));
// 同日:980803~980803
assertEquals(1, YYYMMDDUtils.countDays("0980803", "0980803"));
assertEquals(2, YYYMMDDUtils.countDays("0980803", "0980804"));
// 同月份測試:980803~980823
assertEquals(21, YYYMMDDUtils.countDays("0980803", "0980823"));
// 跨月份測試:980803~980923
assertEquals(52, YYYMMDDUtils.countDays("0980803", "0980923"));
// 跨年度測試:980803~990803
assertEquals(366, YYYMMDDUtils.countDays("0980803", "0990803"));
}
```
◎ float countMonths (day1,day2)
◎ long countMonths (month1,month2)
* 適用於:**YYYMMDD, YYYMM**
* 計算涵蓋月數,原則同 countDays(),同月算一月、前一月為-1。
* YYYMMDD 回傳 float,前後未滿一月部分,依日數比例計算。
``` java
// 同月份
assertEquals(1 / 30.0, YYYMMDDUtils.countMonths("1070401", "1070401"));
assertEquals(2 / 30.0, YYYMMDDUtils.countMonths("1070401", "1070402"));
// 同月份/反向
assertEquals(-1 / 30.0, YYYMMDDUtils.countMonths("1070402", "1070401"));
// 跨月份
assertEquals((2 / 31.0) + (1 / 30.0), YYYMMDDUtils.countMonths("1070330", "1070401"));
assertEquals((2 / 31.0) + (2 / 30.0), YYYMMDDUtils.countMonths("1070330", "1070402"));
assertEquals((2 / 31.0) + 2 + (2 / 30.0), YYYMMDDUtils.countMonths("1070330", "1070602"));
assertEquals(1 + (1 / 30.0), YYYMMDDUtils.countMonths("1070301", "1070401"));
assertEquals(2, YYYMMDDUtils.countMonths("1070301", "1070430"));
// 跨月份/反向 : 四月未列計。
assertEquals((-1 / 31.0), YYYMMDDUtils.countMonths("1070401", "1070331"));
// 跨月份/反向 : 四月未列計。
assertEquals((-2 / 31.0), YYYMMDDUtils.countMonths("1070401", "1070330"));
// 跨月份/反向 : 4/1 一天、3/30、3/31 兩天。
assertEquals((-2 / 31.0) + (-1 / 30.0), YYYMMDDUtils.countMonths("1070402", "1070330"));
// 跨月份/反向 : 四月未列計。
assertEquals(-1, YYYMMDDUtils.countMonths("1070401", "1070301"));
// 跨月份/反向 : 四月的29天 加上 整個三月。
assertEquals((-29 / 30.0) - 1, YYYMMDDUtils.countMonths("1070430", "1070301"));
```
TODO : 有考慮增加的 METHOD : int age(birthday,now)