package java8.date;
import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
/**
* @author Gu Yuanhua
* created time 2018/7/5 23:39
*/
class DateTimeUtils {
/**
* 一個星期的週期爲7天
*/
private static final int PERIOD = 7;
/**
* 打印某年星期幾的全部對應日期
*
* @param startDate 某年
* @param week 星期幾
*/
static void queryDayOfWeek(LocalDate startDate,
LocalDate endDate, String week) {
// 計算兩個日期間的天數
long days = ChronoUnit.DAYS.between(startDate, endDate);
// 開始時間不能晚於結束時間!
if (days < 0) {
throw new DateTimeException("開始時間不能晚於結束時間!");
}
// 建立一個集合存放全部的星期幾
List<LocalDate> allWeek;
if (days < PERIOD) {
// 時間間隔小於7天
allWeek = lessThanSevenDays(startDate, days, week);
} else {
// 時間間隔大於7天
allWeek = moreThanSevenDays(startDate, endDate, week);
}
// 打印星期幾對應的全部日期
allWeek.forEach(System.out::println);
}
/**
* 時間間隔大於7天
*
* @param startDate 開始日期
* @param endDate 結束日期
* @param week 星期幾
* @return 對應日期集合
*/
private static List<LocalDate> moreThanSevenDays(LocalDate startDate, LocalDate endDate, String week) {
// 中文日期轉化英文日期
String englishWeek = weekFormat(week);
// 當前日期指針
LocalDate currentDate = startDate;
List<LocalDate> weeks = new ArrayList<>();
// 找到第一個星期幾
for (int i = 1; i <= PERIOD; i++) {
if (Objects.equals(englishWeek, currentDate.getDayOfWeek().toString())) {
// 第一個星期幾放入集合
weeks.add(currentDate);
// 當前日期指針指向下一個星期幾
currentDate=currentDate.plusWeeks(1);
break;
}
currentDate = currentDate.plusDays(1);
}
// 找到剩下的全部星期幾
while (currentDate.getYear () < endDate.getYear () ||
currentDate.getMonthValue () < endDate.getMonthValue () ||
currentDate.getDayOfMonth () < endDate.getDayOfMonth ()) {
// 當前星期幾放入集合
weeks.add (currentDate);
// 當前日期指針指向下一個星期幾
currentDate = currentDate.plusWeeks (1);
}
return weeks;
}
/**
* 時間間隔小於7天
*
* @param startDate 開始日期
* @param days 時間間隔
* @param week 星期幾
* @return 對應日期集合
*/
private static List<LocalDate> lessThanSevenDays(LocalDate startDate, long days, String week) {
// 中文日期轉化英文日期
String englishWeek = weekFormat(week);
List<LocalDate> weeks = new ArrayList<>();
// days可能爲0,也就是開始日期等於結束日期,因此須要i<=days
for (int i = 0; i <= days; i++) {
// 若是時間間隔內找到這個星期幾
if (Objects.equals(startDate.getDayOfWeek().toString(), englishWeek)) {
weeks.add(startDate);
return weeks;
}
startDate = startDate.plusDays(i);
}
// 7天時間間隔遍歷後依然沒有找到
throw new DateTimeException("時間間隔小於7天,沒法找到:" + week);
}
/**
* 將中文日期轉化爲英文
*
* @param week 中文日期
* @return 英文日期
*/
private static String weekFormat(String week) {
switch (week) {
case "星期一":
week = "MONDAY";
break;
case "星期二":
week = "TUESDAY";
break;
case "星期三":
week = "WEDNESDAY";
break;
case "星期四":
week = "THURSDAY";
break;
case "星期五":
week = "FRIDAY";
break;
case "星期六":
week = "SATURDAY";
break;
case "星期日":
week = "SUNDAY";
break;
default:
throw new DateTimeException("日期不正確");
}
return week;
}
}
測試代碼
package java8.date;
import org.junit.Test;
import java.time.LocalDate;
/**
* @author Gu Yuanhua
* created time 2018/7/3 22:47
*/
public class LocalDateTimeTest {
@Test
public void testLodalDateTime() {
System.out.println("============開始時間晚於結束時間的測試==============");
// 開始時間晚於結束時間的測試
LocalDate startDate = LocalDate.of(2019, 1, 6);
LocalDate endDate = LocalDate.of(2018, 1, 1);
DateTimeUtils.queryDayOfWeek(startDate,endDate, "星期二");
System.out.println("============時間間隔小於7天的測試==============");
// 時間間隔小於7天的測試
LocalDate startDate1 = LocalDate.of(2018, 1, 1);
LocalDate endDate1 = LocalDate.of(2018, 1, 6);
DateTimeUtils.queryDayOfWeek(startDate1, endDate1, "星期二");
System.out.println("===========時間間隔大於7天的測試===============");
// 時間間隔大於7天的測試
LocalDate startDate2 = LocalDate.of(2018, 6, 6);
LocalDate endDate2 = LocalDate.of(2019, 6, 6);
DateTimeUtils.queryDayOfWeek(startDate2, endDate2, "星期二");
}
}
使用Stream以及Groovy方式
/**
* 獲取兩個日期間隔的全部日期
*
* @param startDate 開始日期
* @param endDate 結束日期
* @return 全部日期的集合
*/
static List<LocalDate> queryWeek(LocalDate startDate, LocalDate endDate, String week) {
String englishWeek = weekFormat (week);
long days = ChronoUnit.DAYS.between (startDate, endDate);
if (days < 0) {
throw new DateTimeException ("開始時間不能晚於結束時間!");
}
return Stream.iterate (startDate, date -> date.plusDays (1))
.limit (days + 1) // 總的天數是間隔天數+1
.filter (date -> Objects.equals (date.getDayOfWeek ().toString (), englishWeek))
.collect (Collectors.toList ());
}
static def queryWeek(LocalDate startDate, LocalDate endDate, String week) {
def englishWeek = weekFormat(week)
long days = ChronoUnit.DAYS.between(startDate, endDate)
def weeks = [] // 全部星期幾對應日期集合
def currentDate = startDate // 當前日期
if (days < 0) {
throw new DateTimeException("開始時間不能晚於結束時間!")
} else {
(days + 1).times {
if (currentDate.getDayOfWeek().toString() == englishWeek) {
weeks << currentDate
}
currentDate = currentDate.plusDays(1) // 更新當前日期
}
return weeks
}
}
時間複雜度O(n)優化爲O(n/7)
/**
* 獲取兩個日期間隔的全部日期
*
* @param startDate 開始日期
* @param endDate 結束日期
* @return 全部日期的集合
*/
static List<LocalDate> queryWeek(LocalDate startDate, LocalDate endDate, String week) {
String englishWeek = weekFormat (week);
long days = ChronoUnit.DAYS.between (startDate, endDate);
if (days < 0) {
throw new DateTimeException ("開始時間不能晚於結束時間!");
} else {
LocalDate firstDate = Stream.iterate (startDate, date -> date.plusDays (1))
.filter (date -> Objects.equals (date.getDayOfWeek ().toString (), englishWeek))
.findFirst ()
.get ();
return Stream.iterate (firstDate, date -> date.plusWeeks (1))
.limit (days / 7 + 1) // 總的天數是間隔天數+1
.filter (date -> Objects.equals (date.getDayOfWeek ().toString (), englishWeek))
.collect (Collectors.toList ());
}
}
static def queryWeek(LocalDate startDate, LocalDate endDate, String week) {
def englishWeek = weekFormat(week)
long days = ChronoUnit.DAYS.between(startDate, endDate)
def weeks = [] // 全部星期幾對應日期集合
def currentDate = startDate // 當前日期
if (days < 0) {
throw new DateTimeException("開始時間不能晚於結束時間!")
} else {
// 找到第一個星期幾,也就是把第一個星期幾做爲工做日期頭指針
7.times {
if (currentDate.getDayOfWeek().toString() == englishWeek) {
return
}
currentDate = currentDate.plusDays(1) // 更新當前日期
}
// 查找剩餘全部的星期幾
(days / 7 + 1).times {
if (currentDate.getDayOfWeek().toString() == englishWeek) {
weeks << currentDate
}
currentDate = currentDate.plusWeeks(1) // 更新當前日期
}
return weeks
}
}