diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Helpers.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Helpers.scala index fd0dff6b..616385ac 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Helpers.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/Helpers.scala @@ -16,6 +16,8 @@ package com.xiaomi.duckling.dimension.time +import java.time.temporal.ChronoUnit + import com.xiaomi.duckling.Types._ import com.xiaomi.duckling.dimension.implicits._ import com.xiaomi.duckling.dimension.time.enums.Grain @@ -23,6 +25,7 @@ import com.xiaomi.duckling.dimension.time.enums.Grain._ import com.xiaomi.duckling.dimension.time.form.{TimeOfDay, Month => _} import com.xiaomi.duckling.dimension.time.helper.TimeDataHelpers.hour import com.xiaomi.duckling.dimension.time.predicates.{TimeDatePredicate, TimePredicate} +import com.xiaomi.duckling.dimension.time.Types.InstantValue object Helpers { @@ -66,4 +69,20 @@ object Helpers { } else td2 } + def countGrains(start: InstantValue, end: InstantValue): Int = { + val a = start.datetime.toLocalDatetime + val b = end.datetime.toLocalDatetime + val n = start.grain match { + case NoGrain | Second => ChronoUnit.SECONDS.between(a, b) + case Minute => ChronoUnit.MINUTES.between(a, b) + case Hour => ChronoUnit.HOURS.between(a, b) + case Day => ChronoUnit.DAYS.between(a, b) + case Week => ChronoUnit.WEEKS.between(a, b) + case Month => ChronoUnit.MONTHS.between(a, b) + case Quarter => ChronoUnit.MONTHS.between(a, b) / 3 + case Year => ChronoUnit.YEARS.between(a, b) + } + n.intValue() + } + } diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/predicates.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/predicates.scala index 055d0a9e..4332ba5d 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/predicates.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/predicates.scala @@ -187,6 +187,11 @@ object predicates { case _ => false } + val isInterval: Predicate = { + case Token(Time, td: TimeData) => td.timePred.isInstanceOf[TimeIntervalsPredicate] + case _ => false + } + val isIntervalOfDay: Predicate = { case Token(Time, td: TimeData) => td.form match { diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Repeat.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Repeat.scala index 022a9950..ea32ab1a 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Repeat.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Repeat.scala @@ -25,6 +25,7 @@ import com.xiaomi.duckling.dimension.time.grain.TimeGrain import com.xiaomi.duckling.dimension.time.Types._ import com.xiaomi.duckling.dimension.time.enums.Grain import com.xiaomi.duckling.dimension.time.form.Form +import com.xiaomi.duckling.dimension.time.Helpers.countGrains case object Repeat extends Dimension with Rules { override val name: String = "Repeat" @@ -35,7 +36,9 @@ case object Repeat extends Dimension with Rules { case class RepeatData(interval: Option[DurationData] = None, n: Option[Int] = None, start: Option[TimeData] = None, - workdayType: Option[WorkdayType] = None) + workdayType: Option[WorkdayType] = None, + repeatGrain: Option[Grain] = None, + repeatNFromInterval: Option[TimeData] = None) extends Resolvable { override def resolve(context: Context, @@ -48,7 +51,19 @@ case class RepeatData(interval: Option[DurationData] = None, } case None => (None, true) } - if (success) Some(RepeatValue(interval, n, instant, workdayType), false) + val repeatN = repeatNFromInterval match { + case Some(intervalTimeData) => + intervalTimeData.resolve(context, options) match { + case Some((tv: TimeValue, _)) => + tv.timeValue match { + case IntervalValue(start, end) => Some(countGrains(start, end)) + case _ => None + } + case _ => None + } + case _ => None + } + if (success) Some(RepeatValue(interval, n.orElse(repeatN), instant, repeatGrain = repeatNFromInterval.map(_.timeGrain), workdayType), false) else None } } @@ -63,6 +78,7 @@ case class RepeatData(interval: Option[DurationData] = None, case class RepeatValue(interval: Option[DurationData] = None, n: Option[Int] = None, start: Option[(TimeValue, Option[Form])] = None, + repeatGrain: Option[Grain] = None, workdayType: Option[WorkdayType] = None) extends ResolvedValue { diff --git a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Rules.scala b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Rules.scala index ff4aaea1..d6311ad7 100644 --- a/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Rules.scala +++ b/duckling-fork-chinese/core/src/main/scala/com/xiaomi/duckling/dimension/time/repeat/Rules.scala @@ -22,11 +22,12 @@ import com.xiaomi.duckling.Types._ import com.xiaomi.duckling.dimension.DimRules import com.xiaomi.duckling.dimension.implicits._ import com.xiaomi.duckling.dimension.matcher.GroupMatch -import com.xiaomi.duckling.dimension.matcher.Prods.{regexMatch, singleRegexMatch} -import com.xiaomi.duckling.dimension.time.{form, Time, TimeData} +import com.xiaomi.duckling.dimension.matcher.Prods.regexMatch +import com.xiaomi.duckling.dimension.time.{form, GrainWrapper, Time, TimeData} import com.xiaomi.duckling.dimension.time.duration.{Duration, DurationData} import com.xiaomi.duckling.dimension.time.enums.{Grain, Hint} -import com.xiaomi.duckling.dimension.time.predicates.{isAPartOfDay, isATimeOfDay, isHint, isNotLatent, isTimeDatePredicate, IntersectTimePredicate, TimeDatePredicate, TimeIntervalsPredicate} +import com.xiaomi.duckling.dimension.time.helper.TimeDataHelpers.intersect +import com.xiaomi.duckling.dimension.time.predicates._ trait Rules extends DimRules with LazyLogging { /** @@ -155,4 +156,16 @@ trait Rules extends DimRules with LazyLogging { workdaysTime(rd, td) } ) + + // 周一到周五的早上八点 + val ruleIntervalTime = Rule( + name = "