zoukankan      html  css  js  c++  java
  • 一月分四周的JAVA实现方法

    需求:给定任意一个月,如何按照中国周的习惯,把一个月分成四个时间段

    (1)以自然周为划分依据

    (2)不能跨月

    (3)把首尾自然周,天数较少的合并到其最近的自然周里面

    (4)最后结果应该是吧一个月分成四个时间段,并给出每段的起止日期

    大概需求就如上所述,不废话,上代码:(以封装好在main()函数里,直接copy即可,记得导相应的包和新建实体类)

    public class one_month_four_week {
    
        public static void main(String[] args) {
    
        int year = 2017;
        int month = 10;//改成你要的年月,运行即可查看结果
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, year);
        cal.set(Calendar.MONTH, month - 1);// -1才正确
        int days = cal.getActualMaximum(Calendar.DATE);// Calendar.DAY_OF_MONTH也对
        System.out.println("首先,计算这个月有" + days + "天");
    
        String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };// 国外一周起始
        int[] chinaWeek = { 7, 1, 2, 3, 4, 5, 6 };// 对应成中国一周的第几天
    
        SimpleDateFormat str_date_format = new SimpleDateFormat("yyyy-MM-dd");
    
        List<EachDayAttr> monthDay = new ArrayList<>();
        int week_of_month = 1;
        for (int i = 1; i <= days; i++) {
            EachDayAttr oneDay = new EachDayAttr();
            oneDay.setWhich(i);
            // 计算这个月的每一天,对应星期几
            String dayStr = year + "-" + month + "-" + i;
            Date daysDate = null;
            try {
            daysDate = str_date_format.parse(dayStr);
            } catch (ParseException e) {
            e.printStackTrace();
            }
            cal.setTime(daysDate);
            int w1 = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的第几天
            int which_day_chinaWeek = chinaWeek[w1];
            System.out.println("该月的第"+ i +"天,该星期(外国习惯)的第"+ w1 +"天:"+ weekDays[w1] +">>对应中国周的第"+ which_day_chinaWeek +"天!");
            //关键:该月每一天对应,中国周里面的第几周
            if (which_day_chinaWeek == 1 && monthDay.size() > 0) {// 星期一,中国习惯里新的一周的开始
            week_of_month++;
            oneDay.setWeek(week_of_month);
            } else {
            oneDay.setWeek(week_of_month);
            }
            monthDay.add(oneDay);
        }
    
        // 分组:按中国习惯分组
        Map<Integer, List<EachDayAttr>> weekGroup = new TreeMap<>();
    
        for (EachDayAttr oneDay : monthDay) {
            if (weekGroup.containsKey(oneDay.getWeek())) {
            weekGroup.get(oneDay.getWeek()).add(oneDay);
            } else {
            List<EachDayAttr> addGroup = new ArrayList<>();
            addGroup.add(oneDay);
            weekGroup.put(oneDay.getWeek(), addGroup);
            }
        }
        
        // 再分组:合并成四周
        if (weekGroup.size() == 4) {
            // weekGroup不做处理
        } else if (weekGroup.size() == 5) {
            if (weekGroup.get(1).size() < weekGroup.get(5).size()) {
            weekGroup.get(2).addAll(weekGroup.get(1));
            weekGroup.remove(1);
            } else {
            weekGroup.get(4).addAll(weekGroup.get(5));
            weekGroup.remove(5);
            }
        } else if (weekGroup.size() == 6) {
            weekGroup.get(2).addAll(weekGroup.get(1));
            weekGroup.get(5).addAll(weekGroup.get(6));
            weekGroup.remove(1);
            weekGroup.remove(6);
        }
    
        // 吧weekGroup按天数排序,取最小为开始日期,最大为结束日期即可
        for (Entry<Integer, List<EachDayAttr>> entry : weekGroup.entrySet()) {
            Collections.sort(entry.getValue(), new Comparator<EachDayAttr>() {
            public int compare(EachDayAttr day1, EachDayAttr day2) {
                return day1.getWhich() - day2.getWhich();
            }
            });
        }
        // 最后从分好组、排好序的weekGroup中取值封装
        // weekGroup-->entry中健为整数,而值为list<?>集合
        Map<Integer, String[]> rtResult = new HashMap<>();
        int signWeek = 1;
        for (Entry<Integer, List<EachDayAttr>> entry : weekGroup.entrySet()) {
            String[] addResult = new String[2];
            int firstDay = entry.getValue().get(0).getWhich();
            int lastDay = entry.getValue().get(entry.getValue().size() - 1).getWhich();
            addResult[0] = year + "-" + month + "-" + firstDay;
            addResult[1] = year + "-" + month + "-" + lastDay;
            rtResult.put(signWeek, addResult);
            signWeek++;
        }
    
        // 至此,输出看下结果
        for (Entry<Integer, String[]> entry : rtResult.entrySet()) {
            System.out.println("----该月第"+ entry.getKey() +"周-----");
            System.out.println("开始日期:" + entry.getValue()[0]);
            System.out.println("结束日期:" + entry.getValue()[1]);
        }
    
        }
    }

    总结:上面方法。涉及知识点其实挺多,也是日常项目中遇到的比较多的,比如Calendar这个出来日期的类,还有分组排序、map的遍历等;

    加上自定义的实体类,强迫症的小伙伴可以看下:

    public class EachDayAttr {
        private int which;
        
        private int week;
        
        private int flag;

    //get和set方法省略 }

    最后。附上SQL大神直接用sql是怎么把一个月按中国周分的(这里一个月最多会有六周,为了更清楚,笔者有改动,但该sql精华不变)

    select min(dt) 一周开始, max(dt) 一周结束, count(flag) 该周天数, ROW_NUMBER() over(order by 1) as 周数
            from (
            select level rn, 
                   trunc(to_date(201707,'yyyymm'), 'mm') + level - 1 dt,
                   max(decode (to_char(trunc(to_date(201707,'yyyymm'), 'mm') + level - 1, 'd'), 2, level, 0)) over(order by level) flag
              from dual
        connect by level <= last_day(trunc(to_date(201707,'yyyymm'))) - trunc(to_date(201707,'yyyymm'), 'mm') + 1
        )
          group by flag
          order by min(rn)

    这是在mybatis里面实现的,传入的参数是整形的年月,比如int yyyymm = 201707;

  • 相关阅读:
    Linux 文件 目录结构探索
    实践 : Ubuntu 上 Testlink 部署
    Linux 查找安装包所在目录的常用方法
    selenium + python 测试环境搭建 (WINDOWS)
    EntityFramework 学习 一 Entity Framework结构体系
    castle windsor学习-------Container Events 容器的事件
    castle windsor学习----ComponentModel construction contributors
    castle windsor学习----- CastleComponentAttribute 特性注册
    castle windsor学习-----Inline dependencies 依赖
    castle windsor学习-----Registering components by conventions
  • 原文地址:https://www.cnblogs.com/zz-3m23d-begining/p/7754868.html
Copyright © 2011-2022 走看看