package cn.iocoder.yudao.module.iot.service.rule.scene; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.CharPool; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum; import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotCurrentTimeConditionMatcher; import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotTimerConditionEvaluator; import lombok.experimental.UtilityClass; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.List; /** * IoT 场景规则时间匹配工具类 *
* 提供时间条件匹配的通用方法,供 {@link IotCurrentTimeConditionMatcher} 和 {@link IotTimerConditionEvaluator} 共同使用。
*
* @author HUIHUI
*/
@Slf4j
@UtilityClass
public class IotSceneRuleTimeHelper {
/**
* 时间格式化器 - HH:mm:ss
*/
private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
/**
* 时间格式化器 - HH:mm
*/
private static final DateTimeFormatter TIME_FORMATTER_SHORT = DateTimeFormatter.ofPattern("HH:mm");
/**
* 判断是否为日期时间操作符
*
* @param operatorEnum 操作符枚举
* @return 是否为日期时间操作符
*/
public static boolean isDateTimeOperator(IotSceneRuleConditionOperatorEnum operatorEnum) {
return operatorEnum == IotSceneRuleConditionOperatorEnum.DATE_TIME_GREATER_THAN
|| operatorEnum == IotSceneRuleConditionOperatorEnum.DATE_TIME_LESS_THAN
|| operatorEnum == IotSceneRuleConditionOperatorEnum.DATE_TIME_BETWEEN;
}
/**
* 判断是否为时间操作符(包括日期时间操作符和当日时间操作符)
*
* @param operatorEnum 操作符枚举
* @return 是否为时间操作符
*/
public static boolean isTimeOperator(IotSceneRuleConditionOperatorEnum operatorEnum) {
return operatorEnum != IotSceneRuleConditionOperatorEnum.TIME_GREATER_THAN
&& operatorEnum != IotSceneRuleConditionOperatorEnum.TIME_LESS_THAN
&& operatorEnum != IotSceneRuleConditionOperatorEnum.TIME_BETWEEN
&& !isDateTimeOperator(operatorEnum);
}
/**
* 执行时间匹配逻辑
*
* @param operatorEnum 操作符枚举
* @param param 参数值
* @return 是否匹配
*/
public static boolean executeTimeMatching(IotSceneRuleConditionOperatorEnum operatorEnum, String param) {
try {
LocalDateTime now = LocalDateTime.now();
if (isDateTimeOperator(operatorEnum)) {
// 日期时间匹配(时间戳,秒级)
long currentTimestamp = now.atZone(ZoneId.systemDefault()).toEpochSecond();
return matchDateTime(currentTimestamp, operatorEnum, param);
} else {
// 当日时间匹配(HH:mm:ss)
return matchTime(now.toLocalTime(), operatorEnum, param);
}
} catch (Exception e) {
log.error("[executeTimeMatching][operatorEnum({}) param({}) 时间匹配异常]", operatorEnum, param, e);
return false;
}
}
/**
* 匹配日期时间(时间戳,秒级)
*
* @param currentTimestamp 当前时间戳
* @param operatorEnum 操作符枚举
* @param param 参数值
* @return 是否匹配
*/
@SuppressWarnings("EnhancedSwitchMigration")
public static boolean matchDateTime(long currentTimestamp, IotSceneRuleConditionOperatorEnum operatorEnum,
String param) {
try {
// DATE_TIME_BETWEEN 需要解析两个时间戳,单独处理
if (operatorEnum == IotSceneRuleConditionOperatorEnum.DATE_TIME_BETWEEN) {
return matchDateTimeBetween(currentTimestamp, param);
}
// 其他操作符只需要解析一个时间戳
long targetTimestamp = Long.parseLong(param);
switch (operatorEnum) {
case DATE_TIME_GREATER_THAN:
return currentTimestamp > targetTimestamp;
case DATE_TIME_LESS_THAN:
return currentTimestamp < targetTimestamp;
default:
log.warn("[matchDateTime][operatorEnum({}) 不支持的日期时间操作符]", operatorEnum);
return false;
}
} catch (Exception e) {
log.error("[matchDateTime][operatorEnum({}) param({}) 日期时间匹配异常]", operatorEnum, param, e);
return false;
}
}
/**
* 匹配日期时间区间
*
* @param currentTimestamp 当前时间戳
* @param param 参数值(格式:startTimestamp,endTimestamp)
* @return 是否匹配
*/
public static boolean matchDateTimeBetween(long currentTimestamp, String param) {
List