任意時間間隔內某星期幾的所有對應日期
阿新 • • 發佈:2018-11-25
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
}
}