diff --git a/powerjob-common/src/main/java/tech/powerjob/common/enums/TimeExpressionType.java b/powerjob-common/src/main/java/tech/powerjob/common/enums/TimeExpressionType.java index 92d90d88..5c4625ca 100644 --- a/powerjob-common/src/main/java/tech/powerjob/common/enums/TimeExpressionType.java +++ b/powerjob-common/src/main/java/tech/powerjob/common/enums/TimeExpressionType.java @@ -23,7 +23,9 @@ public enum TimeExpressionType { CRON(2), FIXED_RATE(3), FIXED_DELAY(4), - WORKFLOW(5); + WORKFLOW(5), + + DAILY_TIME_INTERVAL(11); private final int v; @@ -31,7 +33,7 @@ public enum TimeExpressionType { /** * 首次计算触发时间时必须计算出一个有效值 */ - public static final List INSPECT_TYPES = Collections.unmodifiableList(Lists.newArrayList(CRON.v)); + public static final List INSPECT_TYPES = Collections.unmodifiableList(Lists.newArrayList(CRON.v, DAILY_TIME_INTERVAL.v)); public static TimeExpressionType of(int v) { for (TimeExpressionType type : values()) { diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/auxiliary/TimeOfDay.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/auxiliary/TimeOfDay.java new file mode 100644 index 00000000..1100d067 --- /dev/null +++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/auxiliary/TimeOfDay.java @@ -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. + * + *

The hour is in 24-hour convention, meaning values are from 0 to 23.

+ * PowerJob learn from quartz + * + * @since 2.0.3 + * + * @author James House + * @author Zemian Deng + */ +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 + "]"; + } +} + diff --git a/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/auxiliary/impl/DailyTimeIntervalStrategyHandler.java b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/auxiliary/impl/DailyTimeIntervalStrategyHandler.java new file mode 100644 index 00000000..92fe2629 --- /dev/null +++ b/powerjob-server/powerjob-server-core/src/main/java/tech/powerjob/server/core/scheduler/auxiliary/impl/DailyTimeIntervalStrategyHandler.java @@ -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 daysOfWeek; + } +}