Pu Zhibing
2025-04-22 d138293736414a314467a2641e6116ff263ead48
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package com.ruoyi.bussiness.utils;
 
import cn.hutool.core.date.DateUtil;
 
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
 
public class PaymentCycleHelper {
 
    // 格式化日期为 "yyyy-MM"
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
 
    // 根据 25% 首付款支付时间计算首笔付款周期
    public static String getFirstPaymentCycle(Date firstPaymentDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(firstPaymentDate);
 
        int month = calendar.get(Calendar.MONTH) + 1; // 获取月份(1-12)
 
        if (month >= 10 && month <= 12) {
            // 10月-12月,首笔付款周期为次年1月
            calendar.add(Calendar.YEAR, 1);
            calendar.set(Calendar.MONTH, Calendar.JANUARY); // 设置为1月
        } else if (month >= 1 && month <= 3) {
            // 1月-3月,首笔付款周期为当年4月
            calendar.set(Calendar.MONTH, Calendar.APRIL);
        } else if (month >= 4 && month <= 6) {
            // 4月-6月,首笔付款周期为当年7月
            calendar.set(Calendar.MONTH, Calendar.JULY);
        } else if (month >= 7 && month <= 9) {
            // 7月-9月,首笔付款周期为当年10月
            calendar.set(Calendar.MONTH, Calendar.OCTOBER);
        }
 
        // 返回首笔付款周期格式 "yyyy-MM"
        return sdf.format(calendar.getTime());
    }
 
    public static String getCurrentQuarter(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
 
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1; // 获取月份(1-12)
 
        // 计算当前季度的起始月份
        int quarterStartMonth = ((month - 1) / 3) * 3 + 1;
 
        return String.format("%d-%02d", year, quarterStartMonth);
    }
 
    /**
     * 获取季度信息
     * @param date
     * @param offset
     * @return
     */
    public static String getQuarterByOffset(Date date, int offset) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
 
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1; // Java中月份是从0开始的
 
        // 当前季度索引:0(Q1),1(Q2),2(Q3),3(Q4)
        int currentQuarter = (month - 1) / 3;
 
        // 计算目标季度的索引
        int targetQuarter = currentQuarter + offset;
 
        // 处理跨年情况
        year += targetQuarter / 4;
        targetQuarter = (targetQuarter % 4 + 4) % 4; // 保证结果在0~3之间
 
        // 获取目标季度的起始月份
        int quarterStartMonth = targetQuarter * 3 + 1;
 
        return String.format("%d-%02d", year, quarterStartMonth);
    }
 
    // 根据首笔付款日期往后推 20 期,计算分期支付周期
    public static String getQuarterlyPaymentCycles(Date firstPaymentDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(firstPaymentDate);
 
        // 获取首笔付款周期
        String firstPaymentCycle = getFirstPaymentCycle(firstPaymentDate);
        try {
            calendar.setTime(sdf.parse(firstPaymentCycle));  // 将首笔付款周期解析为日期
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
 
        // 往后推 20 期,每期为3个月
        String[] paymentCycles = new String[20];
        for (int i = 0; i < 20; i++) {
            paymentCycles[i] = sdf.format(calendar.getTime());
            calendar.add(Calendar.MONTH, 3);  // 每次增加 3 个月
        }
 
        return String.join(",", Arrays.asList(paymentCycles));
    }
 
    // 根据当前季度首笔付款日期往后推 20 期,计算分期支付周期
    public static List<String> getQuarterlyPaymentCyclesList(Date firstPaymentDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(firstPaymentDate);
 
        // 获取首笔付款周期
        String firstPaymentCycle = getCurrentQuarter(firstPaymentDate);
        try {
            calendar.setTime(sdf.parse(firstPaymentCycle));  // 将首笔付款周期解析为日期
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
 
        // 往后推 20 期,每期为3个月
        String[] paymentCycles = new String[20];
        for (int i = 0; i < 20; i++) {
            paymentCycles[i] = sdf.format(calendar.getTime());
            calendar.add(Calendar.MONTH, 3);  // 每次增加 3 个月
        }
        return Arrays.asList(paymentCycles);
    }
 
 
    // 根据首笔付款日期往后推 4 期,计算分期支付周期
    public static List<String> getQuarterlyPaymentCyclesFour(Date firstPaymentDate) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(firstPaymentDate);
 
        // 获取首笔付款周期
        String firstPaymentCycle = getFirstPaymentCycle(firstPaymentDate);
        try {
            calendar.setTime(sdf.parse(firstPaymentCycle));  // 将首笔付款周期解析为日期
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
 
        // 往后推 20 期,每期为3个月
        String[] paymentCycles = new String[4];
        for (int i = 0; i < 4; i++) {
            paymentCycles[i] = sdf.format(calendar.getTime());
            calendar.add(Calendar.MONTH, 3);  // 每次增加 3 个月
        }
        return Arrays.asList(paymentCycles);
    }
 
    /**
     * 计算 25% 首付款支付时间属于 20 期中的第几期
     *
     * @param firstPaymentDate 25% 首付款支付时间(Date 类型)
     * @return 期数(1~20),超出则返回 -1
     */
    public static int getPaymentPeriod(Date firstPaymentDate) {
        //判断时间超过5年,则直接返回20
        long month = DateUtil.betweenMonth(new Date(),firstPaymentDate,true);
        if(month >= 60){
            return 20;
        }
        List<String> times = getQuarterlyPaymentCyclesList(firstPaymentDate);
 
        //获取当前日期季度
        String current = getCurrentQuarter(new Date());
 
        // 计算当前属于哪一期
        for (int i = 0; i <= times.size(); i++) {
            String itemTime = times.get(i);
            if (itemTime.equals(current)) {
                return i;
            }
        }
        // 如果当前日期超出 20 期,则返回 -1
        return 0;
    }
 
    /**
     * 将 Date 转换为 LocalDate
     *
     * @param date Date 类型的日期
     * @return LocalDate 类型的日期
     */
    private static LocalDate convertToLocalDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }
 
 
    public static void main(String[] args) {
        System.out.println(getPaymentPeriod(DateUtil.parseDate(" 2023-10-03")));;
    }
 
}