Joda 时间:计算到下一个完整间隔的时间

问题描述

我正在实施一个应用程序,用户可以在其中创建具有截止日期的任务并重复它们,例如每 x 天、每 x 周、每 x 个月等重复一次。

当任务到期时,我想根据定义的时间间隔计算下一个(重复)到期日期。我的实施几周有效,但几个月无效,因为我无法将几个月转换为分钟。

AlarmHelper.java

// Works
static LocalDateTime getNextWeeklyIntervalDate(LocalDateTime creationTime,LocalDateTime dueTime,int intervalInWeeks) {
    int intervalInMinutes = Weeks.weeks(intervalInWeeks).toStandardMinutes().getMinutes();
    int timePassed = Minutes.minutesBetween(creationTime,dueTime).getMinutes();
    int rest = timePassed % intervalInMinutes;
    int minutesToNextFullInterval = intervalInMinutes - rest;
    return dueTime.plusMinutes(minutesToNextFullInterval );
}

// How to implement this analogous to weekly,but for monthly intervals? toStandardMinutes() does not exist for months  
static LocalDateTime getNextMonthlyIntervalDate(LocalDateTime creationTime,int intervalInMonth) {
    int intervalInMinutes = Months.months(intervalInMonth).toStandardMinutes().getMinutes(); // toStandardMinutes() does not exist
}

AlarmHelperTest.java

// User created the task on 01.01.2021 (January 1st,2021) and want to repeat it weekly.
// So the intervals are 08.01.2021,15.01.2021 etc.
// In the test the task is due on 12.01.2021,which means the next weekly interval is fulfilled on 15.01.2021.

//The test passes
 @Test
 public void TestGetNextWeeklyIntervalDate() {
    LocalDateTime creation = createLocalDateTime("01.01.2021 06:30:00");
    LocalDateTime due = createLocalDateTime("12.01.2021 05:30:00");
    LocalDateTime expected = createLocalDateTime("15.01.2021 06:30:00");
    LocalDateTime result = AlarmHelper.getNextWeeklyIntervalDate(creation,due,1);
    assertEquals(expected,result);
}

解决方法

注意:Home Page of Joda-Time

查看以下通知

Joda-Time 是 Java 的事实上的标准日期和时间库 在 Java SE 8 之前。现在要求用户迁移到 java.time (JSR-310)。

因此,我建议您使用 java.time API 使用以下方法进行操作:

  1. LocalDateTime#isBefore
  2. LocalDateTime#plusWeeks
  3. LocalDateTime#plusMonths

使用 java.time API:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDateTime creation = createLocalDateTime("01.01.2021 06:30:00");
        LocalDateTime due = createLocalDateTime("12.01.2021 05:30:00");
        System.out.println(getNextWeeklyIntervalDate(creation,due,1));
        System.out.println(getNextMonthlyIntervalDate(creation,1));
    }

    static LocalDateTime getNextWeeklyIntervalDate(LocalDateTime creationTime,LocalDateTime dueTime,int intervalInWeeks) {
        LocalDateTime ldt = creationTime;
        while (ldt.isBefore(dueTime)) {
            ldt = ldt.plusWeeks(intervalInWeeks);
        }
        return ldt;
    }

    static LocalDateTime getNextMonthlyIntervalDate(LocalDateTime creationTime,int intervalInMonth) {
        LocalDateTime ldt = creationTime;
        while (ldt.isBefore(dueTime)) {
            ldt = ldt.plusMonths(intervalInMonth);
        }
        return ldt;
    }

    static LocalDateTime createLocalDateTime(String dateTimeStr) {
        return LocalDateTime.parse(dateTimeStr,DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss",Locale.ENGLISH));
    }
}

输出:

2021-01-15T06:30
2021-02-01T06:30

Joda-time API 中也提供了这些方法,即您需要更改的是解析日期时间字符串和获取 LocalDateTime 的方式。

使用 Joda-time API:

import org.joda.time.LocalDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalDateTime creation = createLocalDateTime("01.01.2021 06:30:00");
        LocalDateTime due = createLocalDateTime("12.01.2021 05:30:00");
        System.out.println(getNextWeeklyIntervalDate(creation,int intervalInMonth) {
        LocalDateTime ldt = creationTime;
        while (ldt.isBefore(dueTime)) {
            ldt = ldt.plusMonths(intervalInMonth);
        }
        return ldt;
    }

    static LocalDateTime createLocalDateTime(String dateTimeStr) {
        DateTimeFormatter dtf = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm:ss");
        LocalDateTime ldt = dtf.parseDateTime(dateTimeStr).toLocalDateTime();
        return ldt;
    }
}

输出:

2021-01-15T06:30:00.000
2021-02-01T06:30:00.000

如您所见,除了 createLocalDateTime 中的代码外,所有内容对于 java.time 和 Joda-time API 都是相同的。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...