feat: support DailyTimeInterval #558

This commit is contained in:
tjq 2023-02-11 15:22:40 +08:00
parent 3f7d4328e9
commit 9f2f68344c
3 changed files with 320 additions and 2 deletions

View File

@ -23,7 +23,9 @@ public enum TimeExpressionType {
CRON(2), CRON(2),
FIXED_RATE(3), FIXED_RATE(3),
FIXED_DELAY(4), FIXED_DELAY(4),
WORKFLOW(5); WORKFLOW(5),
DAILY_TIME_INTERVAL(11);
private final int v; private final int v;
@ -31,7 +33,7 @@ public enum TimeExpressionType {
/** /**
* 首次计算触发时间时必须计算出一个有效值 * 首次计算触发时间时必须计算出一个有效值
*/ */
public static final List<Integer> INSPECT_TYPES = Collections.unmodifiableList(Lists.newArrayList(CRON.v)); public static final List<Integer> INSPECT_TYPES = Collections.unmodifiableList(Lists.newArrayList(CRON.v, DAILY_TIME_INTERVAL.v));
public static TimeExpressionType of(int v) { public static TimeExpressionType of(int v) {
for (TimeExpressionType type : values()) { for (TimeExpressionType type : values()) {

View File

@ -0,0 +1,238 @@
package tech.powerjob.server.core.scheduler.auxiliary;
import java.io.Serializable;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
/**
* Represents a time in hour, minute and second of any given day.
*
* <p>The hour is in 24-hour convention, meaning values are from 0 to 23.</p>
* <a href="https://github.com/quartz-scheduler/quartz">PowerJob learn from quartz</a>
*
* @since 2.0.3
*
* @author James House
* @author Zemian Deng <saltnlight5@gmail.com>
*/
public class TimeOfDay implements Serializable {
private static final long serialVersionUID = 2964774315889061771L;
private final int hour;
private final int minute;
private final int second;
/**
* Create a TimeOfDay instance for the given hour, minute and second.
*
* @param hour The hour of day, between 0 and 23.
* @param minute The minute of the hour, between 0 and 59.
* @param second The second of the minute, between 0 and 59.
* @throws IllegalArgumentException if one or more of the input values is out of their valid range.
*/
public TimeOfDay(int hour, int minute, int second) {
this.hour = hour;
this.minute = minute;
this.second = second;
validate();
}
/**
* Create a TimeOfDay instance for the given hour and minute (at the zero second of the minute).
*
* @param hour The hour of day, between 0 and 23.
* @param minute The minute of the hour, between 0 and 59.
* @throws IllegalArgumentException if one or more of the input values is out of their valid range.
*/
public TimeOfDay(int hour, int minute) {
this.hour = hour;
this.minute = minute;
this.second = 0;
validate();
}
private void validate() {
if(hour < 0 || hour > 23)
throw new IllegalArgumentException("Hour must be from 0 to 23");
if(minute < 0 || minute > 59)
throw new IllegalArgumentException("Minute must be from 0 to 59");
if(second < 0 || second > 59)
throw new IllegalArgumentException("Second must be from 0 to 59");
}
/**
* Create a TimeOfDay instance for the given hour, minute and second.
*
* @param hour The hour of day, between 0 and 23.
* @param minute The minute of the hour, between 0 and 59.
* @param second The second of the minute, between 0 and 59.
* @throws IllegalArgumentException if one or more of the input values is out of their valid range.
*/
public static TimeOfDay hourMinuteAndSecondOfDay(int hour, int minute, int second) {
return new TimeOfDay(hour, minute, second);
}
/**
* Create a TimeOfDay instance for the given hour and minute (at the zero second of the minute).
*
* @param hour The hour of day, between 0 and 23.
* @param minute The minute of the hour, between 0 and 59.
* @throws IllegalArgumentException if one or more of the input values is out of their valid range.
*/
public static TimeOfDay hourAndMinuteOfDay(int hour, int minute) {
return new TimeOfDay(hour, minute);
}
/**
* The hour of the day (between 0 and 23).
*
* @return The hour of the day (between 0 and 23).
*/
public int getHour() {
return hour;
}
/**
* The minute of the hour.
*
* @return The minute of the hour (between 0 and 59).
*/
public int getMinute() {
return minute;
}
/**
* The second of the minute.
*
* @return The second of the minute (between 0 and 59).
*/
public int getSecond() {
return second;
}
/**
* Determine with this time of day is before the given time of day.
*
* @return true this time of day is before the given time of day.
*/
public boolean before(TimeOfDay timeOfDay) {
if(timeOfDay.hour > hour)
return true;
if(timeOfDay.hour < hour)
return false;
if(timeOfDay.minute > minute)
return true;
if(timeOfDay.minute < minute)
return false;
if(timeOfDay.second > second)
return true;
if(timeOfDay.second < second)
return false;
return false; // must be equal...
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof TimeOfDay))
return false;
TimeOfDay other = (TimeOfDay)obj;
return (other.hour == hour && other.minute == minute && other.second == second);
}
@Override
public int hashCode() {
return (hour + 1) ^ (minute + 1) ^ (second + 1);
}
/** Return a date with time of day reset to this object values. The millisecond value will be zero. */
public Date getTimeOfDayForDate(Date dateTime) {
if (dateTime == null)
return null;
Calendar cal = Calendar.getInstance();
cal.setTime(dateTime);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
cal.clear(Calendar.MILLISECOND);
return cal.getTime();
}
/**
* Create a TimeOfDay from the given date, in the system default TimeZone.
*
* @param dateTime The java.util.Date from which to extract Hour, Minute and Second.
*/
public static TimeOfDay hourAndMinuteAndSecondFromDate(Date dateTime) {
return hourAndMinuteAndSecondFromDate(dateTime, null);
}
/**
* Create a TimeOfDay from the given date, in the given TimeZone.
*
* @param dateTime The java.util.Date from which to extract Hour, Minute and Second.
* @param tz The TimeZone from which relate Hour, Minute and Second for the given date. If null, system default
* TimeZone will be used.
*/
public static TimeOfDay hourAndMinuteAndSecondFromDate(Date dateTime, TimeZone tz) {
if (dateTime == null)
return null;
Calendar cal = Calendar.getInstance();
cal.setTime(dateTime);
if(tz != null)
cal.setTimeZone(tz);
return new TimeOfDay(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
}
/**
* Create a TimeOfDay from the given date (at the zero-second), in the system default TimeZone.
*
* @param dateTime The java.util.Date from which to extract Hour and Minute.
*/
public static TimeOfDay hourAndMinuteFromDate(Date dateTime) {
return hourAndMinuteFromDate(dateTime, null);
}
/**
* Create a TimeOfDay from the given date (at the zero-second), in the system default TimeZone.
*
* @param dateTime The java.util.Date from which to extract Hour and Minute.
* @param tz The TimeZone from which relate Hour and Minute for the given date. If null, system default
* TimeZone will be used.
*/
public static TimeOfDay hourAndMinuteFromDate(Date dateTime, TimeZone tz) {
if (dateTime == null)
return null;
Calendar cal = Calendar.getInstance();
cal.setTime(dateTime);
if(tz != null)
cal.setTimeZone(tz);
return new TimeOfDay(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE));
}
public static TimeOfDay from(String hms) {
String[] split = hms.split(":");
if (split.length != 3) {
throw new IllegalArgumentException("invalid TimeOfDay, make pattern like 15:30:10");
}
return new TimeOfDay(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
}
@Override
public String toString() {
return "TimeOfDay[" + hour + ":" + minute + ":" + second + "]";
}
}

View File

@ -0,0 +1,78 @@
package tech.powerjob.server.core.scheduler.auxiliary.impl;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.apache.commons.lang3.time.DateUtils;
import tech.powerjob.common.OmsConstant;
import tech.powerjob.common.enums.TimeExpressionType;
import tech.powerjob.common.serialize.JsonUtils;
import tech.powerjob.common.utils.CommonUtils;
import tech.powerjob.server.core.scheduler.auxiliary.TimeOfDay;
import tech.powerjob.server.core.scheduler.auxiliary.TimingStrategyHandler;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
/**
* DailyTimeIntervalStrategyHandler
* @author 550w
* @date 2027/02/15
*/
public class DailyTimeIntervalStrategyHandler implements TimingStrategyHandler {
@Override
public TimeExpressionType supportType() {
return TimeExpressionType.DAILY_TIME_INTERVAL;
}
@Override
@SneakyThrows
public void validate(String timeExpression) {
DailyTimeIntervalExpress ep = JsonUtils.parseObject(timeExpression, DailyTimeIntervalExpress.class);
CommonUtils.requireNonNull(ep.interval, "interval can't be null or empty in DailyTimeIntervalExpress");
CommonUtils.requireNonNull(ep.startTimeOfDay, "startTimeOfDay can't be null or empty in DailyTimeIntervalExpress");
CommonUtils.requireNonNull(ep.endTimeOfDay, "endTimeOfDay can't be null or empty in DailyTimeIntervalExpress");
TimeOfDay startTime = TimeOfDay.from(ep.startTimeOfDay);
TimeOfDay endTime = TimeOfDay.from(ep.endTimeOfDay);
if (endTime.before(startTime)) {
throw new IllegalArgumentException("endTime should after startTime!");
}
}
@Override
public Long calculateNextTriggerTime(Long preTriggerTime, String timeExpression, Long startTime, Long endTime) {
return null;
}
@Data
static class DailyTimeIntervalExpress implements Serializable {
/**
* 时间间隔
*/
private Long interval;
/**
* 每天激活的时间起点格式为18:30:00 代表 18点30分00秒激活
*/
private String startTimeOfDay;
/**
* 每日激活的时间终点格式同上
*/
private String endTimeOfDay;
/* ************ 非必填字段 ************ */
/**
* 时间单位默认秒
*/
private String intervalUnit;
/**
* 每周的哪几天激活空代表每天都激活
*/
private Set<Integer> daysOfWeek;
}
}