订阅周期计算

86 阅读1分钟

ChronoUnit.MONTHS.between(start, now) 计算周期是以31天为一个整月,设置订阅时如果使用plusMonths往后推有效时长,但是周期计算使用上面的方法就会有错误

@Test
public void testMain() throws ParseException, ParseException {
    // 测试数据
    String dateString = "2025-03-01 14:12:35.0";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    Date startTime = sdf.parse(dateString);
    String intervalUnit = "MONTH";
    Integer intervalCount = 1;

    // 调用待测方法
    int payableCycle = (int) (intervalCount(intervalUnit, intervalCount, startTime) + 1);
    int paidCycle = 24 - 23;
    boolean b = payableCycle - paidCycle <= 0;

    // 验证结果
    // Assertions.assertTrue(b);

    LocalDateTime start = DateUtil.toLocalDateTime(startTime);
    LocalDateTime end = start.plusMonths(1);
    LocalDateTime localDateTime2 = start.plusDays(30);
    LocalDateTime localDateTime3 = start.plusDays(31);


    // 验证计算月份差的方法
    int i = calculateMonthDifference(start, end);
    Assertions.assertEquals(1, i);

    LocalDateTime end2 = LocalDateTime.of(2025, 02, 27, 14, 13, 30);
    int i2 = calculateMonthDifference(start, end2);
    Assertions.assertEquals(1, i2);

    LocalDateTime localDateTime = end.plusMonths(1);
    int i1 = calculateMonthDifference(end, localDateTime);
    Assertions.assertEquals(1, i1);

    int i3 = calculateMonthDifference(start, localDateTime);
    Assertions.assertEquals(2, i3);

    LocalDateTime localDateTime1 = start.plusMonths(2);
    int i4 = calculateMonthDifference(start, localDateTime1);
    Assertions.assertEquals(2, i4);
}


public static long intervalCount(String intervalUnit, Integer intervalCount, Date startTime) {
    LocalDateTime start = DateUtil.toLocalDateTime(startTime);
    // LocalDateTime now = LocalDateTime.now();
    // LocalDateTime now = LocalDateTime.of(2025, 02, 28, 14, 13, 30);
    LocalDateTime now = LocalDateTime.of(2025, 04, 01, 14, 13, 30);
    switch (intervalUnit) {
        case "DAY":
            return ChronoUnit.DAYS.between(start, now) / intervalCount;
        case "WEEK":
            return ChronoUnit.WEEKS.between(start, now) / intervalCount;
        case "YEAR":
            return ChronoUnit.YEARS.between(start, now) / intervalCount;
        case "MONTH":
        default:
            return ChronoUnit.MONTHS.between(start, now) / intervalCount;
    }
}

```
public static int calculateMonthDifference(LocalDateTime start, LocalDateTime end) {
    // 计算粗略的月份差
    int monthsDiff = (end.getYear() - start.getYear()) * 12
            + (end.getMonthValue() - start.getMonthValue());

    // 获取根据月份差调整后的时间点
    LocalDateTime adjustedTime = start.plusMonths(monthsDiff);

    // 若当前时间早于调整后的时间点,说明月份差需减1
    if (end.isBefore(adjustedTime)) {
        monthsDiff--;
    }

    // 确保结果非负
    return Math.max(monthsDiff, 0);
}
```
```