mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-05 19:09:32 +00:00
commit
3d164206d3
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -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)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user