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
}
}