Java 日期 不同月按周分组

2023-11-15

日期按月、按周次分组

今天接到需求,要求按月份分开周次

12月31号和新一年的1月1号拆开两个组:[{‘2020-12 第五周 ’:['2020-12-28','2020-12-31']},{‘2021-01 第一周 ’:['2021-01-01','2021-01-03']}]

咋一看,这不搞事情嘛。。。

先把最基本的工具类的函数熟悉一下:

calendar.get(Calendar.WEEK_OF_MONTH) // 这个月在第几周
calendar.getActualMaximum(Calendar.DAY_OF_MONTH) //当月最大天数
calendar.get(Calendar.DAY_OF_WEEK) //周几 
calendar.setFirstDayOfWeek(Calendar.MONDAY); //设置周一为一周的开始

好像该有的函数都有了,那就开始撸了

噼里啪啦整了一顿之后,终于整出了一个初版,测试多次,暂无发现有逻辑BUG,如有望及时提出

测试按月分组一年的数据,耗时约16ms

暂时收工,源码奉上:

/**
     * 根据时间刻度 转化成对应的周
     * eg: 2021-01-01 - 2020-03-05
     *
     * @return {
     * "2021-01 第一周":['2021-01-01','2021-01-03']
     * "2021-01 第二周":['2021-01-04','2021-01-10']
     * ....
     * "2021-03 第一周":['2021-03-01','2021-03-05']
     * }
     */
    public static Map<String, Date[]> getWeekOfMonthStartAndEnd(String startDate, String endDate) throws ParseException {
        final int dayTimeOffset = 24 * 60 * 60 * 1000;
        final String formatKey = "%s 第%d周";
        checkNotEmpty(startDate, endDate);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat keyFormat = new SimpleDateFormat("yyyy-MM");
        Date _start = format.parse(startDate);
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTime(_start);
        if (startDate.equals(endDate)) {
            //同一天
            int idx = calendar.get(Calendar.WEEK_OF_MONTH);
            return Collections.singletonMap(String.format(formatKey, startDate.substring(0, 7), idx), new Date[]{_start, _start});
        }
        Date _end = format.parse(endDate);
        //日期偏移量 (日)
        long dayOffset = (_end.getTime() - _start.getTime()) / dayTimeOffset + 1;
        if (dayOffset < 0) {
            throw new IllegalArgumentException("结束时间必须大于开始时间");
        }
        // --------------------------------处理数据-------------------------------//
        long spanDay = 0; // 累加日期
        int last;
        Map<String, Date[]> result = new LinkedHashMap<>((int) (spanDay / 7) + 1);
        do {
            //result Key 值
            int idx = calendar.get(Calendar.WEEK_OF_MONTH); //当前在这个月的第几周
            String key = String.format(formatKey, keyFormat.format(calendar.getTime()), idx);
            // 0 星期天 1 周一 2 周二 3 周三 4 周四 5 周五 6 周六
            int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;// 周几
            int maxDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); // 当前月最大的天数
            int days = calendar.get(Calendar.DAY_OF_MONTH);
            last = maxDays - days;
            //选择开头的一天
            Date date1 = calendar.getTime(); // value[0]
            if (week > 0) {
                //这周剩下的几天
                int i = 7 - week;
                //添加剩余的几天  30 31 / 01 ==> add 2 days
                if (i > last) {
                    calendar.add(Calendar.DAY_OF_MONTH, last);
                    result.put(key, new Date[]{date1, calendar.getTime()});
                    calendar.add(Calendar.DAY_OF_MONTH, 1); // 到达下一个月
                    spanDay = spanDay + last + 1;
                } else if (i + spanDay >= dayOffset) {
                    //最后一轮
                    result.put(key, new Date[]{date1, _end});
                    spanDay = dayOffset;
                } else {
                    //添加剩余一整周
                    calendar.add(Calendar.DAY_OF_MONTH, i);
                    result.put(key, new Date[]{date1, calendar.getTime()});
                    spanDay = spanDay + i + 1;
                    calendar.add(Calendar.DAY_OF_MONTH, 1); // 到达下一周周一
                }
            } else {
                result.put(key, new Date[]{date1, date1});
                calendar.add(Calendar.DAY_OF_MONTH, 1); // 到达下一周周一
                spanDay++;
            }
        } while (spanDay < dayOffset);
        return result;
    }

    private static void checkNotEmpty(String... args) {
        for (String arg : args) {
            if (StringUtils.isEmpty(arg)) {
                throw new IllegalArgumentException("argument is empty!");
            }
        }
    }

注意:SimpleDateFormat会涉及线程安全的问题,如果需要频繁调用的情景下,建议使用ThreadLocal对象

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 日期 不同月按周分组 的相关文章

  • 无法在 Android 10 中创建目录

    我无法在 android 10 中创建目录 它可以在 android Oreo 之前的设备上运行 我尝试了两种创建文件夹的方法 Using File mkdir File f new File Environment getExternal
  • 具有更高可见性的重写方法是良好的实践吗?

    回答这个问题 如何使用 GUI 使用 PaintComponent 初始化 GUI 然后添加基于鼠标的 GUI https stackoverflow com questions 21336141 how to gui using pain
  • 如何在spring mvc中从控制器名称+操作名称获取映射的URL?

    是否有现有的解决方案可以从 Spring MVC3 中的 控制器名称 操作名称 获取映射的 URL 例如 asp net mvc 或 Rails 中的 UrlHelper 我觉得非常有用 thx 也许 你想要这样的东西 in your Co
  • 对话框上的 EditText 不返回任何文本

    我太累了 找不到错误 我没有发现任何错误 但我没有从 editText 收到任何文本 请看下面的代码 活动密码 xml
  • eclipse中导入项目文件夹图标

    我在 Eclipse 工作区中新导入的 Maven 项目有J and M项目文件夹顶部的图标 项目和包资源管理器 而其他导入的 Maven 项目只有一个J icon 有人可以解释其中的区别吗 该项目有J装饰器被称为 Java 项目和具有M装
  • 如何在 JSP 中导入类?

    我是一个完全的JSP初学者 我正在尝试使用java util List在 JSP 页面中 我需要做什么才能使用除以下类之外的类java lang 使用以下导入语句进行导入java util List 顺便说一句 要导入多个类 请使用以下格式
  • 主线程如何在该线程之前运行?

    我有以下代码 public class Derived implements Runnable private int num public synchronized void setA int num try Thread sleep 1
  • 记录骆驼路线

    我的项目中有几个 Camel 上下文 如果可能的话 我想以逆向工程方式记录路线 因为我们希望保持与上下文相关的文档最新 最好的方法是什么 我们倾向于预先实际设计路线 并使用来自EIP book http www eaipatterns co
  • 如何获取 WebElement 的父级[重复]

    这个问题在这里已经有答案了 我试过了 private WebElement getParent final WebElement webElement return webElement findElement By xpath 但我得到
  • RSA OAEP、Golang 加密、Java 解密 -BadPaddingException:解密错误

    我正在尝试解密使用 RSA OAEP 在 Golang 中加密的字符串 但出现 BadPaddingException 解密错误 很难弄清楚我错过了什么 这是Golang加密方法 func encryptString rootPEM io
  • Git 无法识别重命名和修改的包文件

    我有一个名为的java文件package old myfile java 我已经通过 git 提交了这个文件 然后我将我的包重命名为new所以我的文件在package new myfile java 我现在想将此文件重命名 和内容更改 提交
  • 获取给定类文件的目录路径

    我遇到的代码尝试从类本身的 class 文件所在的同一目录中读取一些配置文件 File configFiles new File this getClass getResource getPath listFiles new Filenam
  • Java - 返回值是否会中断循环?

    我正在编写一些基本上遵循以下格式的代码 public static boolean isIncluded E element Node
  • Spring Security OAuth2简单配置

    我有一个简单的项目 需要以下简单的配置 我有一个 密码 grant type 这意味着我可以提交用户名 密码 用户在登录表单中输入 并在成功时获得 access token 有了该 access token 我就可以请求 API 并获取用户
  • 尝试使用等于“是”或“否”的字符串变量重新启动 do-while 循环

    计算行程距离的非常简单的程序 一周前刚刚开始 我有这个循环用于解决真或假问题 但我希望它适用于简单的 是 或 否 我为此分配的字符串是答案 public class Main public static void main String a
  • 如何通过 Inno Setup for NetBeans 使用自定义 .iss 文件

    我将 Inno Setup 5 与 NetBeans 8 一起使用 并且我已经能够创建一个安装程序来安装该应用程序C users username local appname 但是我希望将其安装在C Programfiles 我如何在 Ne
  • 对象锁定私有类成员 - 最佳实践? (爪哇)

    I asked 类似的问题 https stackoverflow com questions 10548066 multiple object locks in java前几天 但对回复不满意 主要是因为我提供的代码存在一些人们关注的问题
  • 如何在 Quartz 调度程序中每 25 秒运行一次?

    我正在使用 Java 的 Quartz Scheduling API 你能帮我使用 cron 表达式每 25 秒运行一次吗 这只是一个延迟 它不必总是从第 0 秒开始 例如 序列如下 0 00 0 25 0 50 1 15 1 40 2 0
  • 解决错误javax.mail.AuthenticationFailedException

    我不熟悉java中发送邮件的这个功能 我在发送电子邮件重置密码时遇到错误 希望你能给我一个解决方案 下面是我的代码 public synchronized static boolean sendMailAdvance String emai
  • Android AutoCompleteTextView 带芯片

    我不确定我是否使用了正确的词语来描述此 UI 功能 但我已附上我希望在我的应用程序中实现的目标的快照 它由 Go SMS 使用 用户在编辑文本中键入联系人 在用户从完成下拉列表中选择联系人后 该联系人将被插入到编辑文本中 如附图所示 编辑文

随机推荐

  • Basic Level 1013 数素数 (20分)

    题目 令 P i表示第 i 个素数 现任给两个正整数 M N 10 4 请输出 P M到 P N的所有素数 输入格式 输入在一行中给出 M 和 N 其间以空格分隔 输出格式 输出从 P M到 PN的所有素数 每 10 个数字占 1 行 其间
  • Java将数据导出为xml格式

    需求 前后端分离项目 Springboot项目 需要将学生 信息导出为xml文件 StudentController java GetMapping getXml public void studentXml HttpServletRequ
  • linux spi测试程序,spidev测试方法 /how to test spidev

    在设备树中配置spidev 首先需要在设备树配置好spi设备 可参考如下配置 ecspi3 pinctrl names default pinctrl 0 cs gpios dmas dma names rx tx status okay
  • Excel分段线性插值函数实现

    问题 已知 X和Y有下表的对应关系 当一个新的4
  • 高级FPGA设计技巧!多时钟域和异步信号处理解决方案

    有一个有趣的现象 众多数字设计特别是与FPGA设计相关的教科书都特别强调整个设计最好采用唯一的时钟域 换句话说 只有一个独立的网络可以驱动一个设计中所有触发器的时钟端口 虽然这样可以简化时序分析以及减少很多与多时钟域有关的问题 但是由于FP
  • python 连接MySQL数据库

    方式一 pymysql 下载mysql驱动模块 pip install pymysql python 链接mysql示例 导入mysql连接驱动模块 import pymysql host ip地址 port 端口号 user 数据库用户名
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 链表算法的一些领会

    有些题目是一节一节的处理链表 比如reverseBetween ListNode head int m int swapPairs ListNode head reverseInKGroup ListNode head int k 主要考虑
  • docker操作

    一 docker常用操作 1 docker基本命令 批注 第9条 若不写版本号 默认使用lastest 最新版本 建议拉取镜像带上版本号 第10条 其中q是当下id队列的意思 比如查看所有的容器的id docker ps a q docke
  • 华为OD机试真题 Java 实现【支持优先级的队列】【2023 B卷 100分】

    一 题目描述 实现一个支持优先级的队列 高优先级先出队列 同优先级时先进先出 如果两个输入数据和优先级都相同 则后一个数据不入队列被丢弃 队列存储的数据内容是一个整数 二 输入描述 一组待存入队列的数据 包含内容和优先级 三 输出描述 队列
  • 如何设置电脑的固定IP地址

    大家在上网时电脑的IP地址往往都是自动选择的 但在局域网内有时会方便共享文件和监控流量等操作时需要固定的IP地址 下面将简单介绍如何手设置电脑的固定IP地址 步骤 单击电脑网络连接图标 打开网络和共享中心 点击本地连接 点击详细信息 即可看
  • vue列表渲染,鼠标点击改变样式

    话不多说 看下面的代码吧 HTML div ul class nav li item li ul p list ind p div 注 别忘记先引入vue js
  • 淘宝滑块x82y-226流程分析(不涉及逆向)

    分析目标 微信公众号 y小白的笔记 https mp weixin qq com s Py7I6RG7UT9EtdpXlV98aA 只分析验证码加载流程 不说具体细节 版本 226 目标参数slidedata n 成功返回 code 0 r
  • webstorm快速配置react

    以下都是废话 建议看菜鸟教程 也推荐这一个链接 它是React几种基本配置方案 你可以根据需求选择合适的配置 默认你装了node js和npm还有ws2018 2 4 首先在设置 setting 里搜索lang 语言与框架 找到并JavaS
  • 怎样用Java求水仙花数和水仙花数的数量

    首先我们了解一下水仙花数的定义 一个各个位上的数字三次方之和等于他本身的三位数 因此 为了求水仙花数 我们的程序会有以下几个需求 1 首先表示出所有的三位数 用循环表示 这里用for循环示例 2 然后表示出其个位 十位 百位 3 当这个三位
  • Elasticsearch知识点

    目录 1 什么是Elasticsearch 2 Elasticsearch的特点 3 Elasticsearch基础概念 4 Elasticsearch基本数据类型 看这里 5 Elasticsearch基本检索类型 5 1 检索和过滤 5
  • python编译javascript_Js2Py - 把js代码翻译成python代码。也让你可以在python环境里运行js代码。...

    Pure Python JavaScript Translator Interpreter Everything is done in 100 pure Python so it s extremely easy to install an
  • top 命令解释和案例

    文章目录 Top结果 Task分析 CPU分析 内存分析 Top结果 在Linux系统中 top命令用于实时监控系统的性能和进程活动 当你在终端运行top命令时 会显示一个实时的进程列表和系统性能指标 top结果的详细描述如下 第一行 显示
  • Elasticsearch的配置及常见错误

    1 下载Elasticsearch到d盘 在elasticsearch yml中配置两项内容 其中cluster name对应springboot项目中application properties里elasticsearch配置的 elas
  • Java 日期 不同月按周分组

    日期按月 按周次分组 今天接到需求 要求按月份分开周次 12月31号和新一年的1月1号拆开两个组 2020 12 第五周 2020 12 28 2020 12 31 2021 01 第一周 2021 01 01 2021 01 03 咋一看