Merge pull request #562 from eikek/date-proposals

Date proposals
This commit is contained in:
mergify[bot] 2021-01-10 08:45:39 +00:00 committed by GitHub
commit 3d164206d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 36 deletions

View File

@ -40,9 +40,9 @@ val sharedSettings = Seq(
packageTools(logger, dir, v) packageTools(logger, dir, v)
}, },
scalacOptions in (Compile, console) := scalacOptions in (Compile, console) :=
(scalacOptions.value.filter(o => !o.contains("Xlint")) ++ Seq("-Xlint:_,-unused")), (scalacOptions.value.filter(o => !o.contains("-Xlint") && !o.contains("-W"))),
scalacOptions in (Test, console) := scalacOptions in (Test, console) :=
(scalacOptions.value.filter(o => !o.contains("Xlint")) ++ Seq("-Xlint:_,-unused")) (scalacOptions.value.filter(o => !o.contains("-Xlint") && !o.contains("-W")))
) ++ scalafixSettings ) ++ scalafixSettings
val testSettings = Seq( val testSettings = Seq(

View File

@ -17,51 +17,53 @@ object DateFind {
.splitToken(text, " \t.,\n\r/".toSet) .splitToken(text, " \t.,\n\r/".toSet)
.sliding(3) .sliding(3)
.filter(_.length == 3) .filter(_.length == 3)
.map(q => .flatMap(q =>
SimpleDate Stream.emits(
.fromParts(q.toList, lang) SimpleDate
.map(sd => .fromParts(q.toList, lang)
NerDateLabel( .map(sd =>
sd.toLocalDate, NerDateLabel(
NerLabel( sd.toLocalDate,
text.substring(q.head.begin, q(2).end), NerLabel(
NerTag.Date, text.substring(q.head.begin, q(2).end),
q.head.begin, NerTag.Date,
q(1).end q.head.begin,
q(2).end
)
) )
) )
) )
) )
.collect({ case Some(d) => d })
private case class SimpleDate(year: Int, month: Int, day: Int) { case class SimpleDate(year: Int, month: Int, day: Int) {
def toLocalDate: LocalDate = def toLocalDate: LocalDate =
LocalDate.of(if (year < 100) 2000 + year else year, month, day) LocalDate.of(if (year < 100) 2000 + year else year, month, day)
} }
private object SimpleDate { object SimpleDate {
val p0 = (readYear >> readMonth >> readDay).map { case ((y, m), d) => val p0 = (readYear >> readMonth >> readDay).map { case ((y, m), d) =>
SimpleDate(y, m, d) List(SimpleDate(y, m, d))
} }
val p1 = (readDay >> readMonth >> readYear).map { case ((d, m), y) => val p1 = (readDay >> readMonth >> readYear).map { case ((d, m), y) =>
SimpleDate(y, m, d) List(SimpleDate(y, m, d))
} }
val p2 = (readMonth >> readDay >> readYear).map { case ((m, d), y) => val p2 = (readMonth >> readDay >> readYear).map { case ((m, d), y) =>
SimpleDate(y, m, d) List(SimpleDate(y, m, d))
} }
// ymd , ydm, dmy , dym, myd, mdy // ymd , ydm, dmy , dym, myd, mdy
def fromParts(parts: List[Word], lang: Language): Option[SimpleDate] = { def fromParts(parts: List[Word], lang: Language): List[SimpleDate] = {
val p = lang match { val p = lang match {
case Language.English => p2.or(p0).or(p1) case Language.English =>
case Language.German => p1.or(p0).or(p2) p2.alt(p1).map(t => t._1 ++ t._2).or(p2).or(p0).or(p1)
case Language.French => p1.or(p0).or(p2) case Language.German => p1.or(p0).or(p2)
case Language.French => p1.or(p0).or(p2)
} }
p.read(parts) match { p.read(parts) match {
case Result.Success(sd, _) => case Result.Success(sds, _) =>
Either.catchNonFatal(sd.toLocalDate).map(_ => sd).toOption sds.flatMap(sd => Either.catchNonFatal(sd.toLocalDate).toOption.map(_ => sd))
case Result.Failure => case Result.Failure =>
None Nil
} }
} }
@ -89,6 +91,15 @@ object DateFind {
def map[B](f: A => B): Reader[B] = def map[B](f: A => B): Reader[B] =
Reader(read.andThen(_.map(f))) Reader(read.andThen(_.map(f)))
def flatMap[B](f: A => Reader[B]): Reader[B] =
Reader(read.andThen {
case Result.Success(a, rest) => f(a).read(rest)
case Result.Failure => Result.Failure
})
def alt(other: Reader[A]): Reader[(A, A)] =
Reader(words => Result.combine(read(words), other.read(words)))
def or(other: Reader[A]): Reader[A] = def or(other: Reader[A]): Reader[A] =
Reader(words => Reader(words =>
read(words) match { read(words) match {
@ -113,21 +124,31 @@ object DateFind {
sealed trait Result[+A] { sealed trait Result[+A] {
def toOption: Option[A] def toOption: Option[A]
def map[B](f: A => B): Result[B] def map[B](f: A => B): Result[B]
def flatMap[B](f: A => Result[B]): Result[B]
def next[B](r: Reader[B]): Result[(A, B)] def next[B](r: Reader[B]): Result[(A, B)]
} }
object Result { object Result {
final case class Success[A](value: A, rest: List[Word]) extends Result[A] { final case class Success[A](value: A, rest: List[Word]) extends Result[A] {
val toOption = Some(value) val toOption = Some(value)
def map[B](f: A => B): Result[B] = Success(f(value), rest) def flatMap[B](f: A => Result[B]): Result[B] = f(value)
def map[B](f: A => B): Result[B] = Success(f(value), rest)
def next[B](r: Reader[B]): Result[(A, B)] = def next[B](r: Reader[B]): Result[(A, B)] =
r.read(rest).map(b => (value, b)) r.read(rest).map(b => (value, b))
} }
final case object Failure extends Result[Nothing] { final case object Failure extends Result[Nothing] {
val toOption = None val toOption = None
def map[B](f: Nothing => B): Result[B] = this def flatMap[B](f: Nothing => Result[B]): Result[B] = this
def next[B](r: Reader[B]): Result[(Nothing, B)] = this def map[B](f: Nothing => B): Result[B] = this
def next[B](r: Reader[B]): Result[(Nothing, B)] = this
} }
def combine[A](r0: Result[A], r1: Result[A]): Result[(A, A)] =
(r0, r1) match {
case (Success(a0, _), Success(a1, r1)) =>
Success((a0, a1), r1)
case _ =>
Failure
}
} }
private val months = List( private val months = List(

View File

@ -11,19 +11,19 @@ object DateFindSpec extends SimpleTestSuite {
val expect = Vector( val expect = Vector(
NerDateLabel( NerDateLabel(
LocalDate.parse("2016-11-07"), LocalDate.parse("2016-11-07"),
NerLabel("November 7, 2016", NerTag.Date, 50, 60) NerLabel("November 7, 2016", NerTag.Date, 50, 66)
), ),
NerDateLabel( NerDateLabel(
LocalDate.parse("2016-11-07"), LocalDate.parse("2016-11-07"),
NerLabel("November 7, 2016", NerTag.Date, 119, 129) NerLabel("November 7, 2016", NerTag.Date, 119, 135)
), ),
NerDateLabel( NerDateLabel(
LocalDate.parse("2019-09-03"), LocalDate.parse("2019-09-03"),
NerLabel("September 3, 2019", NerTag.Date, 249, 260) NerLabel("September 3, 2019", NerTag.Date, 249, 266)
), ),
NerDateLabel( NerDateLabel(
LocalDate.parse("2016-12-12"), LocalDate.parse("2016-12-12"),
NerLabel("December 12, 2016", NerTag.Date, 1076, 1087) NerLabel("December 12, 2016", NerTag.Date, 1076, 1093)
) )
) )
@ -43,4 +43,30 @@ object DateFindSpec extends SimpleTestSuite {
Vector.empty Vector.empty
) )
} }
test("different date formats") {
assertEquals(
DateFind.findDates("on 11/05/2020", Language.English).toVector,
Vector(
NerDateLabel(
LocalDate.of(2020, 11, 5),
NerLabel("11/05/2020", NerTag.Date, 3, 13)
),
NerDateLabel(
LocalDate.of(2020, 5, 11),
NerLabel("11/05/2020", NerTag.Date, 3, 13)
)
)
)
assertEquals(
DateFind.findDates("on 21/05/2020", Language.English).toVector,
Vector(
NerDateLabel(
LocalDate.of(2020, 5, 21),
NerLabel("21/05/2020", NerTag.Date, 3, 13)
)
)
)
}
} }