Skip to content

Commit

Permalink
fix: support uppercase daysOfWeek and make atto compatible with liter…
Browse files Browse the repository at this point in the history
…al daysOfWeek ranges
  • Loading branch information
mbaechler committed Jan 29, 2025
1 parent 8e42c60 commit 9a56b04
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 5 deletions.
6 changes: 4 additions & 2 deletions modules/atto/shared/src/main/scala/cron4s/atto/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import _root_.atto.{Parser => AttoParser, _}
import atto.Atto._
import cats.implicits._

import java.util.Locale

object Parser extends cron4s.parser.Parser {

import cron4s.parser._
Expand All @@ -45,7 +47,7 @@ object Parser extends cron4s.parser.Parser {

private val sexagesimal: AttoParser[Int] = oneOrTwoDigitsPositiveInt.filter(x => x >= 0 && x < 60)

private val literal: AttoParser[String] = takeWhile1(x => x != ' ' && x != '-')
private val literal: AttoParser[String] = takeWhile1(x => x != ' ' && x != '-' && x != ',')

private val hyphen: AttoParser[Char] = elem(_ == '-', "hyphen")
private val comma: AttoParser[Char] = elem(_ == ',', "comma")
Expand Down Expand Up @@ -95,7 +97,7 @@ object Parser extends cron4s.parser.Parser {
oneOrTwoDigitsPositiveInt.filter(x => (x >= 0) && (x <= 6)).map(ConstNode(_))

private[this] val textualDaysOfWeek: AttoParser[ConstNode] =
literal.filter(DaysOfWeek.textValues.contains).map { value =>
literal.map(_.toLowerCase(Locale.US)).filter(DaysOfWeek.textValues.contains).map { value =>
val index = DaysOfWeek.textValues.indexOf(value)
ConstNode(index, Some(value))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package parsing

import cron4s.parser._

import java.util.Locale
import scala.util.parsing.input._
import scala.util.parsing.combinator._

Expand Down Expand Up @@ -87,7 +88,7 @@ object CronParser extends Parsers with BaseParser {
decimal.filter(_ < 7).map(ConstNode(_))

private[this] val textualDaysOfWeek =
literal.filter(DaysOfWeek.textValues.contains).map { value =>
literal.map(_.toLowerCase(Locale.US)).filter(DaysOfWeek.textValues.contains).map { value =>
val index = DaysOfWeek.textValues.indexOf(value)
ConstNode(index, Some(value))
}
Expand Down
21 changes: 19 additions & 2 deletions tests/shared/src/test/scala/cron4s/CronSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ import org.scalatest.prop.TableDrivenPropertyChecks

import scala.util.{Failure, Success}
import org.scalatest.prop.TableFor3
import CronField._

/**
* Created by alonsodomin on 12/04/2017.
*/
object CronSpec extends TableDrivenPropertyChecks {
import CronField._

final val AllEachExpr = "* * * * * *"
final val AnyDaysExpr = "* * * ? * ?"
Expand Down Expand Up @@ -95,7 +95,8 @@ object CronSpec extends TableDrivenPropertyChecks {
"* 0 0,12 1 */2 *",
"0 0,5,10,15,20,25,30,35,40,45,50,55 * * * *",
"0 1 2-4 * 4,5,6 */3",
"1 5 4 * * mon-2,sun"
"1 5 4 * * mon-2,sun",
"0 0 * ? * MON-WED,FRI-SUN"
)
}

Expand Down Expand Up @@ -132,4 +133,20 @@ trait CronSpec extends Matchers { this: AnyFlatSpec =>
cron.unsafeParse(exprStr) shouldBe ValidExpr
}

it should "parse complexe day express" in {
val value1 = cron("0 0 * ? * MON-WED,FRI-SUN")
value1 shouldBe Right(
CronExpr(
ConstNode[Second](0),
ConstNode[Minute](0),
EachNode[Hour],
AnyNode[DayOfMonth],
EachNode[Month],
SeveralNode(
BetweenNode[DayOfWeek](ConstNode(0), ConstNode(2)),
BetweenNode[DayOfWeek](ConstNode(4), ConstNode(6))
)
)
)
}
}

0 comments on commit 9a56b04

Please sign in to comment.