IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 如何获取特定时间范围内的所有空闲时间段(java版) -> 正文阅读

[Java知识库]如何获取特定时间范围内的所有空闲时间段(java版)

业务场景说明:最近接到一个产品的需求,要求获取某个人,在某一天从上午9点到下午18点内超过两个小时的时间段范围列表,后面用于后继插入其他工作.....

感受:资本家的每个毛孔里都渗透着血和肮脏的东西....吐槽哈, 不要见怪,不要见外,大家都知道哈。

吐槽终究是吐槽,我还不是在被压榨的过程中缓慢前行么,不被压榨,咋生活呀。

本次实现其实是在排班系统存在的前提下,可以获取某人未来的排班信息,用于后期做分段切割的基础数据。下图就是比较直白的展示了24小时内全部空余时间和工作时间的线路图。

那应该如何实现呢?应该如何取出所有的时间段?开始和结束时间如何限制?2h又是如何让计算呢?

我觉得应该需求三个参数去实现,分别是 unitTimeList (占用的时间列表)beginTime (开始时间)endTime(结束时间)。?用开始时间和结束时间确定时间轴,占用时间列表是需要在时间轴中去除的。因此通过这三个参数就能完成上面业务了。

timeService.getIntervalTime(unitTimeList, startTime, endTime);

可是这个函数应该如何实现里面的服务呢??

  • 获取日期区间内每一天的开始和结束时间戳
  • 根据日期分组
  • 设置unitTimeList?到时间轴里面,如果当日无占用列表数据,那么返回一整天
  • 否则,根据开始时间排序
  • 如果当前日期的开始时间与结束时间都在范围内,说明,这天排满了,返回就成。

详细实现还是请跑下面的代码吧...不太好解释...像是算法这玩意一样,有时还真是要一步步跑,才能懂呀。

这次用到两个包分别如下:

  <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
    </dependencies>

?用到的实体?UnitTime、 DateTimeStamp

public class UnitTime {
    /**
     * 当天日期 YYYY-MM-dd
     */
    private String dateTime;
    /**
     * 开始时间戳
     */
    private Long startDate;
    /**
     * 结束时间戳
     */
    private Long endDate;

    public UnitTime() {
    }
}
public class DateTimeStamp {
    private Long startTimeStamp;
    private Long endTimeStamp;

    public DateTimeStamp() {
    }

    public Long getStartTimeStamp() {
        return startTimeStamp;
    }

    public void setStartTimeStamp(Long startTimeStamp) {
        this.startTimeStamp = startTimeStamp;
    }

    public Long getEndTimeStamp() {
        return endTimeStamp;
    }

    public void setEndTimeStamp(Long endTimeStamp) {
        this.endTimeStamp = endTimeStamp;
    }
}

具体的实现类?

public class TimeServiceImpl {
    /**
     * 获取开始日期到结束日期的空闲时间
     *
     * @param unitTimeList 占用的时间列表
     * @param beginTime    开始时间
     * @param endTime      结束时间
     * @return
     */
    public Map<String, List<DateTimeStamp>> getIntervalTime(List<UnitTime> unitTimeList, String beginTime, String endTime) throws ParseException {
        Map<String, List<DateTimeStamp>> resultMap = Maps.newTreeMap();

        // 获取日期区间内每一天的开始和结束时间戳
        Map<String, DateTimeStamp> timeStampMap = DateUtil.getAllTimeStamp(beginTime, endTime);
        //根据日期分组
        Map<String, List<UnitTime>> unitTimeMap = unitTimeList.stream().collect(Collectors.groupingBy(UnitTime::getDateTime));
        for (Map.Entry<String, DateTimeStamp> entry : timeStampMap.entrySet()) {
            // currentUnitTimeList 当天的占用时间
            List<UnitTime> currentUnitTimeList = unitTimeMap.get(entry.getKey());
            List<DateTimeStamp> subList = Lists.newArrayList();
            Long startTs = entry.getValue().getStartTimeStamp();
            Long endTs = entry.getValue().getEndTimeStamp();
            if (currentUnitTimeList.size() == 0) {
                // 当天没有占用时间 则设置一整天的时间
                DateTimeStamp resultTs = new DateTimeStamp();
                resultTs.setStartTimeStamp(startTs);
                resultTs.setEndTimeStamp(endTs);
                subList.add(resultTs);
                resultMap.put(entry.getKey(), subList);
                continue;
            }
            // 根据开始时间排序
            currentUnitTimeList.sort(Comparator.comparing(UnitTime::getStartDate));
            for (UnitTime u : currentUnitTimeList) {
                if (u.getStartDate().longValue() == startTs && u.getEndDate().longValue() == endTs) {
                    // 一整天全部占满
                    break;
                }
                if (u.getStartDate().longValue() > startTs) {
                    // 当前占用的开始时间戳大于当天的开始时间戳 则当天开始时间到当前的开始时间为空闲
                    DateTimeStamp resultTs = new DateTimeStamp();
                    resultTs.setStartTimeStamp(startTs);
                    resultTs.setEndTimeStamp(u.getStartDate().longValue());
                    subList.add(resultTs);
                    if (u.getEndDate().longValue() < endTs) {
                        // 当前结束时间戳小于当天结束时间戳 下一次循环的开始时间等于当前的结束时间
                        startTs = u.getEndDate().longValue();
                        if (currentUnitTimeList.get(currentUnitTimeList.size() - 1).getEndDate().longValue() == startTs) {
                            // 当前为数组最后一个元素 则当前结束时间到当天结束时间空闲
                            DateTimeStamp resultLastTs = new DateTimeStamp();
                            resultLastTs.setStartTimeStamp(startTs);
                            resultLastTs.setEndTimeStamp(endTs);
                            subList.add(resultLastTs);
                        }
                    } else {
                        break;
                    }
                } else {
                    startTs = u.getEndDate().longValue();
                }
            }
            resultMap.put(entry.getKey(), subList);
        }
        return resultMap;
    }
}

用到的工具类?

public class DateUtil {

    private static String LONGDATE_DATE = "yyyy-MM-dd";

    public static Calendar getCalendar(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar;
    }

    /**
     * 时间是否在本月内
     *
     * @param time    时间戳
     * @param pattern 匹配格式
     * @return
     */
    public static boolean isThisTime(long time, String pattern) {
        Date date = new Date(time);
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String param = sdf.format(date);
        String now = sdf.format(new Date());
        if (param.equals(now)) {
            return true;
        }
        return false;
    }

    /**
     * 获取时间段每天开始和结束的时间戳
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static Map<String, DateTimeStamp> getAllTimeStamp(String beginTime, String endTime) throws ParseException {
        Map<String, DateTimeStamp> allTimeStamp = Maps.newHashMap();
        SimpleDateFormat sdf = new SimpleDateFormat(LONGDATE_DATE);
        Calendar cal = getCalendar(sdf.parse(beginTime));
        // 判断是否是同一天
        if (isDay(beginTime, endTime)) {
            setTimeStampList(allTimeStamp, cal);
            return allTimeStamp;
        }

        //获取每天的开始和结束日期
        setTimeStampList(allTimeStamp, cal);
        while (true) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
            if (sdf.parse(endTime).after(cal.getTime())) {
                setTimeStampList(allTimeStamp, cal);
            } else {
                break;
            }
        }
        setTimeStampList(allTimeStamp, cal);
        return allTimeStamp;
    }

    /**
     * 判断两个人日期是否为同一天
     *
     * @param beginDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    public static boolean isDay(String beginDate, String endDate) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(LONGDATE_DATE);
        return DateUtils.isSameDay(sdf.parse(beginDate), sdf.parse(endDate));
    }

    private static void setTimeStampList(Map<String, DateTimeStamp> allTimeStamp, Calendar cal) {
        DateTimeStamp dateTimeStamp = new DateTimeStamp();
        long beginSt = getFirstTime(cal).getTime();
        dateTimeStamp.setStartTimeStamp(beginSt);
        long endSt = getLastTime(cal).getTime();
        dateTimeStamp.setEndTimeStamp(endSt);
        String result = new SimpleDateFormat("yyyy-MM-dd").format(new Date(beginSt));
        allTimeStamp.put(result, dateTimeStamp);
    }

    /**
     * 获取当天起始时间
     *
     * @param todayStart
     * @return
     */
    public static Date getFirstTime(Calendar todayStart) {
        todayStart.set(Calendar.HOUR_OF_DAY, 9);
        todayStart.set(Calendar.MINUTE, 0);
        todayStart.set(Calendar.SECOND, 0);
        todayStart.set(Calendar.MILLISECOND, 0);
        return todayStart.getTime();
    }

    /**
     * 获取当天结束时间
     *
     * @param todayEnd
     * @return
     */
    public static Date getLastTime(Calendar todayEnd) {
        todayEnd.set(Calendar.HOUR_OF_DAY, 18);
        todayEnd.set(Calendar.MINUTE, 0);
        todayEnd.set(Calendar.SECOND, 0);
        todayEnd.set(Calendar.MILLISECOND, 0);
        return todayEnd.getTime();
    }
}

可以用测试类测试一下?

public class TimeTest {
    public static void main(String[] args) {
        List<UnitTime> unitTimeList = Lists.newArrayList();
        UnitTime unitTime = new UnitTime();
        // 2019-11-03 09:00:00 - 2019-11-03 11:00:00
        unitTime.setDateTime("2019-11-03");
        unitTime.setStartDate(1572742800L);
        unitTime.setEndDate(1572750000L);
        unitTimeList.add(unitTime);

        // 2019-11-03 13:20:00 - 2019-11-03 13:50:00
        UnitTime unitTime2 = new UnitTime();
        unitTime2.setDateTime("2019-11-03");
        unitTime2.setStartDate(1572758400L);
        unitTime2.setEndDate(1572760200L);
        unitTimeList.add(unitTime2);

        // 2019-11-03 14:30:00 - 2019-11-03 18:00:00
        UnitTime unitTime3 = new UnitTime();
        unitTime3.setDateTime("2019-11-03");
        unitTime3.setStartDate(1572762600L);
        unitTime3.setEndDate(1572775200L);
        unitTimeList.add(unitTime3);

        TimeServiceImpl timeService = new TimeServiceImpl();

        Map<String, List<DateTimeStamp>> intervalMap = null;
        try {
            intervalMap = timeService.getIntervalTime(unitTimeList, "2019-11-03", "2019-11-03");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(intervalMap);
    }

最终的结果:?

?

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:02:36  更:2022-05-07 11:03:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:06:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码