Skip to content

Commit

Permalink
Merge pull request #232 from du00cs/sequence
Browse files Browse the repository at this point in the history
[DUCK] 节日更新 & 序列时间重做,扩展适用范围
  • Loading branch information
zhangsonglei authored Aug 5, 2024
2 parents ea26ffc + 0afb4e5 commit 98b27a3
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ object Types {

def and(ps: Predicate*): Predicate = {
case token: Token =>
ps.forall(p => p.isDefinedAt(token) && p(token))
val result = ps.forall(p => p.isDefinedAt(token) && p(token))
result
}

def or(ps: Predicate*): Predicate = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,17 @@ trait Rules extends DimRules {
// else if (td1.timeGrain == Day && td2.timeGrain == Hour) None
else {
val hint =
if (td1.timeGrain == Year && td2.hint == MonthOnly) YearMonth
if (td1.timePred.isInstanceOf[SequencePredicate]) Sequence
else if (td1.timeGrain == Year && td2.hint == MonthOnly) YearMonth
else Intersect
// 10号八点,需要去掉AMPM (今天是10号9点时,不应再出20点)
// 今天8点,需要根据当前时间是出8/20点
val _td2 = if (td1.hint == Hint.RecentNominal) td2 else removeAMPM(td2)
val _td1 = FuzzyDayIntervals.enlarge(td1, options.timeOptions.beforeEndOfInterval)
val td = intersect(_td1, _td2).map(_.copy(hint = hint))
tt(td)
hint match {
case Sequence => sequenceProd(_td1, _td2)
case _ => tt(intersect(_td1, _td2).map(_.copy(hint = hint)))
}
}
}
)
Expand Down Expand Up @@ -533,7 +536,7 @@ trait Rules extends DimRules {
case _ =>
if (td1.timeGrain >= td2.timeGrain) {
val cal = calendar(td1, td2)
if (td1.timeGrain > td2.timeGrain && recentHint(td2.hint)) {
if (td1.timeGrain > td2.timeGrain && (td1.timePred.isInstanceOf[SequencePredicate] || recentHint(td2.hint))) {
tt(
TimeData(
ReplacePartPredicate(td1, td2),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,11 @@ object Types {
}

def withYear(y: Int): DuckDateTime = this.copy(date = date.withYear(y))

def withMonth(m: Int): DuckDateTime = this.copy(date = date.withMonth(m))

def withDayOfMonth(d: Int): DuckDateTime = this.copy(date = date.withDayOfMonth(d))
def withHour(h: Int): DuckDateTime = this.copy(time = time.withHour(h))
def withMinute(m: Int): DuckDateTime = this.copy(time = time.withMinute(m))
def withSecond(s: Int): DuckDateTime = this.copy(time = time.withSecond(s))

def to(calendar: Calendar): DuckDateTime = {
calendar match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class LocalHolidayProvider extends HolidayProvider {
val rulePeriodicHolidays: List[(Token, String, String)] = mkRuleHolidays(
// Fixed dates, year over year
List(
(monthDay(1, 10), "中国人民警察节", "中国人民警察节|人民警察节|中国警察节|警察节"),
(monthDay(2, 7), "国际声援南非日", "国际声援南非日|声援南非日"),
(monthDay(2, 15), "中国12亿人口日", "中国12亿人口日"),
(monthDay(2, 21), "反对殖民主义斗争日", "反对殖民主义斗争日|反对殖民制度斗争日"),
Expand Down Expand Up @@ -140,7 +141,7 @@ class LocalHolidayProvider extends HolidayProvider {
(monthDay(12, 12), "双十二", "双十二|双十二电商节"),
(monthDay(12, 12), "西安事变纪念日", "西安事变纪念日"),
(monthDay(12, 13), "南京大屠杀纪念日", "南京大屠杀纪念日"),
(monthDay(12, 13), "南京大屠杀死难者国家公祭日", "南京大屠杀死难者国家公祭日"),
(monthDay(12, 13), "南京大屠杀死难者国家公祭日", "南京大屠杀死难者国家公祭日|国家公祭日"),
(monthDay(12, 2), "全国交通安全日", "全国交通安全日|交通安全日"),
(monthDay(12, 20), "澳门回归纪念日", "澳门回归纪念日|澳门回归日"),
(monthDay(12, 24), "平安夜", "平安夜"),
Expand All @@ -160,7 +161,7 @@ class LocalHolidayProvider extends HolidayProvider {
(monthDay(3, 1), "国际海豹日", "国际海豹日|海豹日"),
(monthDay(3, 12), "植树节", "中国植树节|植树节"),
(monthDay(3, 14), "白色情人节", "白色情人节"),
(monthDay(3, 15), "国际消费者权益日", "国际消费者权益日|世界消费者权益日|消费者权益日|三一五"),
(monthDay(3, 15), "国际消费者权益日", "国际消费者权益日|世界消费者权益日|消费者权益日|三一五|消费者日"),
(monthDay(3, 17), "中国国医节", "中国国医节|国医节"),
(monthDay(3, 17), "圣帕特里克节", "圣帕特里克节"),
(monthDay(3, 21), "世界森林日", "世界森林日|森林日"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,26 +191,68 @@ package object time {
t1 <- resolveTimeData(t, td1)
t2 <- resolveTimeData(t, td2)
} yield {
val to = (td1.timeGrain, td2.timeGrain) match {
case (Year, Month) => t2.copy(start = t2.start.withYear(t1.start.year))
case (Year, Day) => t2.copy(start = t2.start.withYear(t1.start.year))
case (Month, Day) =>
t2.copy(start = t2.start.withMonth(t1.start.month).withYear(t1.start.year))
case (Day, NoGrain) => // 今天现在
t2.copy(
start = t2.start
.withYear(t1.start.year)
.withMonth(t1.start.month)
.withDayOfMonth(t1.start.dayOfMonth)
)
case _ => null
}
val to =
if (td2.timePred.maxGrain.nonEmpty && td1.timeGrain > td2.timePred.maxGrain.get) {
copyGrain(Year, td2.timePred.maxGrain.get, t1, t2)
} else {
(td1.timeGrain, td2.timeGrain) match {
case (Year, Month) => t2.copy(start = t2.start.withYear(t1.start.year))
case (Year, Day) => t2.copy(start = t2.start.withYear(t1.start.year))
case (Month, Day) =>
t2.copy(start = t2.start.withMonth(t1.start.month).withYear(t1.start.year))
case (Day, NoGrain) => // 今天现在
t2.copy(
start = t2.start
.withYear(t1.start.year)
.withMonth(t1.start.month)
.withDayOfMonth(t1.start.dayOfMonth)
)
case _ => null
}
}
if (to == null) EmptySeries
else if (to.start.isBefore(t.start)) (Stream(to), Stream.empty)
else (Stream.empty, Stream(to))
}).getOrElse(EmptySeries)
}

def copy(grain: Grain, t1: DuckDateTime, t2: DuckDateTime): DuckDateTime = {
grain match {
case Grain.Minute => t2.withMinute(t1.minute)
case Grain.Hour => t2.withHour(t1.hour)
case Grain.Day => t2.withDayOfMonth(t1.dayOfMonth)
case Grain.Month => t2.withMonth(t1.month)
case Grain.Year => t2.withYear(t1.year)
case _ => t2
}
}

@scala.annotation.tailrec
def copyGrain(thisGrain: Grain, stopGrain: Grain, t1: TimeObject, t2: TimeObject): TimeObject = {
if (t1.start.date.isInstanceOf[LunarDate]) {
if (thisGrain >= Day && stopGrain < Day) {
val start = t2.start.copy(date = t1.start.date)
val end =
if (t2.end.isEmpty) None
else if (t1.end.isEmpty) t2.end
else t2.end.map(d => d.copy(date = t1.start.date))
val t = t2.copy(start = start, end = end)
copyGrain(Hour, stopGrain, t1, t)
} else t2
} else if (thisGrain > stopGrain) {
val start = copy(thisGrain, t1.start, t2.start)
val end =
if (t2.end.isEmpty) None
else if (t1.end.isEmpty) t2.end
else t2.end.map(copy(thisGrain, t1.end.get, _))
val t = t2.copy(start = start, end = end)
thisGrain.finer() match {
case Some(g) => copyGrain(g, stopGrain, t1, t)
case _ => t2
}
} else t2
}

@scala.annotation.tailrec
def runSequencePredicate(list: List[TimeData])(t: TimeObject,
context: TimeContext): PastFutureTime = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ object Examples extends DimExamples {
(y(2013), List("今年", "这一年")),
(y(2014), List("明年", "下一年")),
(ymd(2013, 12, 30, calendar = Lunar(false)).copy(holiday = "除夕"), List("今年除夕", "大年三十", "年三十")),
(ymdhms(2013, 12, 30, 20, grain=Hour, calendar = Lunar(false)), List("除夕晚上八点")),
(ymd(2021, 12, 29, calendar = Lunar(false), holiday = "除夕"), List("2021年除夕")), // 2021年没有大年三十
(
localDateTimeInterval(
Expand Down Expand Up @@ -148,8 +149,8 @@ object Examples extends DimExamples {
val times = List(
(hms(4, 30, 0), List("现在", "此时", "此刻", "当前", "4:30:00", "04点30分0秒")),
(hm(15, 15), List("下午三点十五", "下午3:15", "15:15", "3:15pm", "3:15p.m", "下午三点一刻", "下午的三点一刻")),
(yMdHms(d=13, H=2, grain = Hour), List("晚上两点")),
(yMdHms(d=12, H=17, grain = Hour), List("晚上五点")),
(ymdhms(d=13, h=2, grain = Hour), List("晚上两点")),
(ymdhms(d=12, h=17, grain = Hour), List("晚上五点")),
(hm(16, 40), List("十六时四十分", "十六点四十")),
(hm(6, 10), List("六点十分", "六点一十")),
(hms(4, 33, 0), List("过三分钟")),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.xiaomi.duckling.dimension.time.helper

import java.time.{LocalDateTime, LocalTime}
import java.time.{LocalDate, LocalDateTime, LocalTime}

import com.github.heqiao2010.lunar.LunarCalendar

Expand All @@ -10,6 +10,7 @@ import com.xiaomi.duckling.Types.{Context, ZoneCN}
import com.xiaomi.duckling.dimension.time.enums._
import com.xiaomi.duckling.dimension.time.enums.Grain._
import com.xiaomi.duckling.dimension.time.Types._
import com.xiaomi.duckling.ranking.Testing
import com.xiaomi.duckling.ranking.Testing.testContext

object TimeValueHelpers {
Expand Down Expand Up @@ -71,8 +72,12 @@ object TimeValueHelpers {

def md(m: Int, d: Int): TimeValue = ymd(2013, m, d)

def yMdHms(y: Int = 2013, M: Int = 2, d: Int = 12, H: Int = 0, m: Int = 0, s: Int = 0, grain: Grain): TimeValue = {
datetime(LocalDateTime.of(y, M, d, H, m, s), grain)
def ymdhms(y: Int = 2013, M: Int = 2, d: Int = 12, h: Int = 0, m: Int = 0, s: Int = 0, grain: Grain, calendar: Calendar = Solar, holiday: Option[String] = None): TimeValue = {
val date = calendar match {
case Solar => SolarDate(LocalDate.of(y, M, d))
case Lunar(leap) => LunarDate(new LunarCalendar(y, M, d, leap))
}
datetime(DuckDateTime(date, LocalTime.of(h, m, s), Testing.testContext.referenceTime.getZone), grain, holiday)
}

def datetimeInterval(dt1: DuckDateTime, dt2: DuckDateTime, g: Grain, holiday: Option[String] = None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ object Examples extends DimExamples {
Hour)
), List("每个月五号的早上")),
(RepeatValue(DurationData(1, Month), start = ymd(m = 3, d = 5)), List("每个月的五号")),
(RepeatValue(DurationData(1, Month), start = yMdHms(M = 3, d = 2, H = 14, grain = Hour)), List("每月2号下午2点")),
(RepeatValue(DurationData(1, Month), start = ymdhms(M = 3, d = 2, h = 14, grain = Hour)), List("每月2号下午2点")),
(RepeatValue(DurationData(1, Week), start = (ymd(d = 13), Some(form.DayOfWeek))), List("每周三", "每个星期三")),
(RepeatValue(DurationData(1, Day), start = (h(8), Some(form.TimeOfDay(Some(8), false)))), List("每天上午八点", "每个上午八点")),
(RepeatValue(workdayType = NonWorkday), List("非工作日", "节假日")),
(RepeatValue(workdayType = Workday, start = (yMdHms(d = 13, H = 3, grain = Hour), Some(form.TimeOfDay(Some(3), false)))), List("工作日三点", "工作日每天三点", "每个工作日三点")),
(RepeatValue(workdayType = Workday, start = (ymdhms(d = 13, h = 3, grain = Hour), Some(form.TimeOfDay(Some(3), false)))), List("工作日三点", "工作日每天三点", "每个工作日三点")),
(RepeatValue(workdayType = Workday, start = (datetimeInterval(
new DuckDateTime(LocalDateTime.of(2013, 2, 12, 8, 0, 0)),
new DuckDateTime(LocalDateTime.of(2013, 2, 12, 12, 0, 0)),
Expand Down

0 comments on commit 98b27a3

Please sign in to comment.