时间维度转换工具类

最近负责一个目标管理模块,需要实现一个让用户选择目标的时间维度功能。实现周目标的时候,本来应该根据这一周在哪个月所占的天数多就归属哪个月,结果让AI实现怎么写都有问题,明明告诉AI周四在哪个月就算哪个月但还是不行,记录一下。项目是jdk7,所以使用Calendar类。

package com.caikw.tsaicy.common.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class DateRangeUtil {

    private static final DateFormat DF = new SimpleDateFormat("yyyy-MM-dd");

    public static final class Target {
        public final String weekText;
        public final String monthText;
        public final String quarterText;
        public final String yearText;
        private Target(String w, String m, String q, String y) {
            this.weekText = w; this.monthText = m;
            this.quarterText = q; this.yearText = y;
        }
    }
    
    /**
     * @param date 当前日期
     * @param type 0=周;1=月,2=季度……
     * @return Object[0]=weekText;Object[1]=startDate;Object[2]=endDate;
     */
    public static Object[] get(Date date,int type){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        String text;
        Date start,end;

        switch(type){  //周
            case 0: {
                Calendar mon = (Calendar) cal.clone();
                mon.setFirstDayOfWeek(Calendar.MONDAY);
                mon.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
                Calendar sun = (Calendar) mon.clone();
                sun.add(Calendar.DATE, 6);
                text = buildWeekText(cal);
                start = mon.getTime();
                end = sun.getTime();
                break;
            }
            case 1: {   //月
                Calendar c1 = (Calendar) cal.clone();
                c1.set(Calendar.DAY_OF_MONTH, 1);
                Calendar c2 = (Calendar) c1.clone();
                c2.set(Calendar.DAY_OF_MONTH, c1.getActualMaximum(Calendar.DAY_OF_MONTH));
                text = buildMonthText(cal);
                start = c1.getTime();
                end = c2.getTime();
                break;
            }
            case 2: {   //季度
                int quarter = cal.get(Calendar.MONTH) / 3 + 1;
                int year = cal.get(Calendar.YEAR);
                Calendar c1 = new GregorianCalendar(year, 3 * quarter - 3, 1);
                Calendar c2 = new GregorianCalendar(year, 3 * quarter - 1, 1);
                c2.set(Calendar.DAY_OF_MONTH, c2.getActualMaximum(Calendar.DAY_OF_MONTH));
                text = buildQuarterText(cal);
                start = c1.getTime();
                end = c2.getTime();
                break;
            }
            case 3: {   //年
                int year = cal.get(Calendar.YEAR);
                Calendar c1 = new GregorianCalendar(year, Calendar.JANUARY, 1);
                Calendar c2 = new GregorianCalendar(year, Calendar.DECEMBER, 31);
                text = buildYearText(cal);
                start = c1.getTime();
                end = c2.getTime();
                break;
            }
            default:
                throw new IllegalArgumentException("type只支持0-3");
        }
        return new Object[]{text,DF.format(start),DF.format(end)};
    }
    
    /**
     * 获取当前日期,前后各maxnum个周的日期表述&起止日期
     * @param date 当前日期
     * @param type 0=周;1=月,2=季度……
     * @param maxnum 前后各几个
     * @return list[0]=weekText;list[1]=startDate;list[2]=endDate;
     */
    public static List<Object[]> getDateList(Date date,int type,int maxnum){
        List<Object[]> list = new ArrayList<>(maxnum *2 +1);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        int field;
        switch(type){
            case 0: field = Calendar.WEEK_OF_YEAR; break;
            case 1: field = Calendar.MONTH; break;
            case 2: field = Calendar.QUARTER; break;
            case 3: field = Calendar.YEAR; break;
            default: throw new IllegalArgumentException("type只支持0-3");
        }

        cal.add(field,-maxnum);
        for(int i = 0; i < maxnum *2 +1; i++){
            list.add(get(cal.getTime(),type));
            cal.add(field,1);
        }
        return list;
    }

    /**
     * 返回Object[0]的内容,某年某月第某周(非今年) 或某月第某周(今年)
     * 
     * @return 
     */
    /* ---------------- 周 ---------------- */
    private static String buildWeekText(Calendar cal) {
        Calendar now = Calendar.getInstance();
        int currentYear = now.get(Calendar.YEAR);

        /* ---- 当前周的周四 ---- */
        Calendar thu = (Calendar) cal.clone();
        thu.setFirstDayOfWeek(Calendar.MONDAY);
        thu.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);

        /* ---- 本周判断 ---- */
        if (thu.get(Calendar.YEAR) == currentYear &&
                thu.get(Calendar.WEEK_OF_YEAR) == now.get(Calendar.WEEK_OF_YEAR)) {
            return "本周";
        }

        int targetYear  = thu.get(Calendar.YEAR);
        int targetMonth = thu.get(Calendar.MONTH);

        /* ---- 1~4 号里有没有周四? ---- */
        boolean thuIn1_4 = false;
        for (int d = 1; d <= 4; d++) {
            Calendar c = new GregorianCalendar(targetYear, targetMonth, d);
            if (c.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
                thuIn1_4 = true;
                break;
            }
        }

        Calendar firstMon;          // 本月第一周的起始周一
        int weekCount = 1;          // 默认从第 1 周开始数

        if (thuIn1_4) {
            /* 情况1:1~4 号出现周四 → 本月第 1 周就是 1~7 号 */
            firstMon = new GregorianCalendar(targetYear, targetMonth, 1);
            // 把 1 号调成周一(可能要去上个月)
            while (firstMon.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
                firstMon.add(Calendar.DATE, -1);
            }
        } else {
        /* 情况2:1~4 号没有周四 → 1 号属于上月最后一周,
                  本月第 1 周是“本月第一个周四”所在周 */
            Calendar firstThu = new GregorianCalendar(targetYear, targetMonth, 1);
            while (firstThu.get(Calendar.DAY_OF_WEEK) != Calendar.THURSDAY) {
                firstThu.add(Calendar.DATE, 1);
            }
            firstMon = (Calendar) firstThu.clone();
            firstMon.add(Calendar.DATE, -3);   // 推到周一
        }

        /* ---- 当前周一(用来数周)---- */
        Calendar mon = (Calendar) thu.clone();
        mon.add(Calendar.DATE, -3);

        /* ---- 从 firstMon 开始数周 ---- */
        while (firstMon.before(mon)) {
            firstMon.add(Calendar.DATE, 7);
            weekCount++;
        }

        return (targetYear == currentYear)
                ? String.format("%d月第%d周", targetMonth + 1, weekCount)
                : String.format("%d年%d月第%d周", targetYear, targetMonth + 1, weekCount);
    }

    /* ---------------- 月 ---------------- */
    private static String buildMonthText(Calendar cal) {
        int tarYear = cal.get(Calendar.YEAR);
        int tarMonth = cal.get(Calendar.MONTH);

        int nowYear = Calendar.getInstance().get(Calendar.YEAR);
        int nowMonth = Calendar.getInstance().get(Calendar.MONTH);

        if(tarYear == nowYear && tarMonth == nowMonth){
            return "本月";
        }
        return (tarYear == nowYear)
                ?String.format("%d月", tarMonth + 1)
                : String.format("%d年%d月", tarYear, tarMonth + 1);
    }

    /* ---------------- 季 ---------------- */
    private static String buildQuarterText(Calendar cal) {
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);   // 0-based
        int quarter = month / 3 + 1;

        int nowYear = Calendar.getInstance().get(Calendar.YEAR);
        int nowMonth = Calendar.getInstance().get(Calendar.MONTH);
        int nowQuarter = nowMonth / 3 + 1;

        if (year == nowYear && quarter == nowQuarter){
            return "本季";
        }
        return String.format("%d年第%d季度", year, quarter);
    }

    /* ---------------- 年 ---------------- */
    private static String buildYearText(Calendar cal) {
        int year = cal.get(Calendar.YEAR);
        int nowYear = Calendar.getInstance().get(Calendar.YEAR);
        return (year == nowYear) ? "本年" : String.format("%d年", year);
    }

    private DateRangeUtil() {}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值