任意时间间隔内某星期几的所有对应日期

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

转载于:https://my.oschina.net/u/3269534/blog/1841144

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值