{"id":13566515,"url":"https://github.com/fthomas/fs2-cron","last_synced_at":"2025-04-04T13:13:33.946Z","repository":{"id":33044574,"uuid":"146017035","full_name":"fthomas/fs2-cron","owner":"fthomas","description":"FS2 streams based on cron expressions","archived":false,"fork":false,"pushed_at":"2025-03-27T16:20:14.000Z","size":947,"stargazers_count":135,"open_issues_count":0,"forks_count":19,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-28T12:09:56.333Z","etag":null,"topics":["cron","cron4s","fs2","functional-programming","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fthomas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-08-24T16:48:32.000Z","updated_at":"2025-03-27T16:20:17.000Z","dependencies_parsed_at":"2023-12-21T13:55:58.684Z","dependency_job_id":"301a49d2-ed18-4705-beef-5ba70fbc3069","html_url":"https://github.com/fthomas/fs2-cron","commit_stats":{"total_commits":597,"total_committers":14,"mean_commits":"42.642857142857146","dds":"0.44388609715242877","last_synced_commit":"db91c1f841ef6805fd7d6c5e046a7a316726d8e3"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Ffs2-cron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Ffs2-cron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Ffs2-cron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fthomas%2Ffs2-cron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fthomas","download_url":"https://codeload.github.com/fthomas/fs2-cron/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182420,"owners_count":20897381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cron","cron4s","fs2","functional-programming","scala"],"created_at":"2024-08-01T13:02:11.105Z","updated_at":"2025-04-04T13:13:33.939Z","avatar_url":"https://github.com/fthomas.png","language":"Scala","readme":"# fs2-cron\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/fthomas/fs2-cron/ci.yml?branch=master)](https://github.com/fthomas/fs2-cron/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/fthomas/fs2-cron/branch/master/graph/badge.svg)](https://codecov.io/gh/fthomas/fs2-cron)\n[![Join the chat at https://gitter.im/fthomas/fs2-cron](https://badges.gitter.im/fthomas/fs2-cron.svg)](https://gitter.im/fthomas/fs2-cron?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![Scaladex](https://index.scala-lang.org/fthomas/fs2-cron/latest.svg?color=blue)](https://index.scala-lang.org/fthomas/fs2-cron/fs2-cron-core)\n[![Scaladoc](https://www.javadoc.io/badge/eu.timepit/fs2-cron-core_2.12.svg?color=blue\u0026label=Scaladoc)](https://javadoc.io/doc/eu.timepit/fs2-cron-core_2.12)\n\n**fs2-cron** is a microlibrary that provides [FS2][FS2] streams based\non [Cron4s][Cron4s] cron expressions or [Calev][Calev] calendar\nevents.\n\nIt is provided for Scala 2.12, 2.13 and `fs2-cron-calev` also for\nScala 3.\n\n## Examples\n\n```scala\nimport cats.effect.IO\nimport cats.effect.unsafe.implicits.global\nimport fs2.Stream\nimport java.time.LocalTime\n\nval printTime = Stream.eval(IO(println(LocalTime.now)))\n```\n\n### Using Cron4s library\n\nRequires the `fs2-cron-cron4s` module:\n\n```scala\nimport cron4s.Cron\nimport eu.timepit.fs2cron.cron4s.Cron4sScheduler\n\nval cronScheduler = Cron4sScheduler.systemDefault[IO]\n// cronScheduler: eu.timepit.fs2cron.Scheduler[IO, cron4s.expr.CronExpr] = eu.timepit.fs2cron.cron4s.Cron4sScheduler$$anon$1@25eea02a\n\nval evenSeconds = Cron.unsafeParse(\"*/2 * * ? * *\")\n// evenSeconds: cron4s.package.CronExpr = CronExpr(\n//   seconds = */2,\n//   minutes = *,\n//   hours = *,\n//   daysOfMonth = ?,\n//   months = *,\n//   daysOfWeek = *\n// )\n\nval scheduled = cronScheduler.awakeEvery(evenSeconds) \u003e\u003e printTime\n// scheduled: Stream[[x]IO[x], Unit] = Stream(..)\n\nscheduled.take(3).compile.drain.unsafeRunSync()\n// 12:17:48.032770646\n// 12:17:50.001097222\n// 12:17:52.000732258\n```\n```scala\nval everyFiveSeconds = Cron.unsafeParse(\"*/5 * * ? * *\")\n// everyFiveSeconds: cron4s.package.CronExpr = CronExpr(\n//   seconds = */5,\n//   minutes = *,\n//   hours = *,\n//   daysOfMonth = ?,\n//   months = *,\n//   daysOfWeek = *\n// )\n\nval scheduledTasks = cronScheduler.schedule(List(\n  evenSeconds      -\u003e Stream.eval(IO(println(LocalTime.now.toString + \" task 1\"))),\n  everyFiveSeconds -\u003e Stream.eval(IO(println(LocalTime.now.toString + \" task 2\")))\n))\n// scheduledTasks: Stream[IO, Unit] = Stream(..)\n\nscheduledTasks.take(9).compile.drain.unsafeRunSync()\n// 12:17:54.001309092 task 1\n// 12:17:55.002303004 task 2\n// 12:17:56.001378253 task 1\n// 12:17:58.001008992 task 1\n// 12:18:00.001058382 task 2\n// 12:18:00.001275186 task 1\n// 12:18:02.001425277 task 1\n// 12:18:04.002083568 task 1\n// 12:18:05.001522523 task 2\n```\n\n#### Cancelling the scheduled task\nUsing `Stream#interruptWhen(haltWhenTrue)`\n\n```scala\nimport cats.effect._\nimport cron4s.Cron\nimport eu.timepit.fs2cron.cron4s.Cron4sScheduler\nimport fs2.Stream\nimport fs2.concurrent.SignallingRef\n\nimport java.time.LocalTime\nimport scala.concurrent.duration._\n\nobject TestApp extends IOApp.Simple {\n  val printTime = Stream.eval(IO(println(LocalTime.now)))\n\n  override def run: IO[Unit] = {\n    val cronScheduler = Cron4sScheduler.systemDefault[IO]\n    val evenSeconds = Cron.unsafeParse(\"*/2 * * ? * *\")\n    val scheduled = cronScheduler.awakeEvery(evenSeconds) \u003e\u003e printTime\n    val cancel = SignallingRef[IO, Boolean](false)\n\n    for {\n      c \u003c- cancel\n      s \u003c- scheduled.interruptWhen(c).repeat.compile.drain.start\n      //prints about 5 times before stop\n      _ \u003c- Temporal[IO].sleep(10.seconds) \u003e\u003e c.set(true)\n    } yield s\n  }\n}\n```\n\n### Using Calev library\n\nRequires the `fs2-cron-calev` module:\n\n```scala\nimport com.github.eikek.calev.CalEvent\nimport eu.timepit.fs2cron.calev.CalevScheduler\n\nval calevScheduler = CalevScheduler.systemDefault[IO]\n// calevScheduler: eu.timepit.fs2cron.Scheduler[IO, CalEvent] = eu.timepit.fs2cron.calev.CalevScheduler$$anon$1@19ab8621\nval oddSeconds = CalEvent.unsafe(\"*-*-* *:*:1/2\")\n// oddSeconds: CalEvent = CalEvent(\n//   weekday = All,\n//   date = DateEvent(year = All, month = All, day = All),\n//   time = TimeEvent(\n//     hour = All,\n//     minute = All,\n//     seconds = List(values = Vector(Single(value = 1, rep = Some(value = 2))))\n//   ),\n//   zone = None\n// )\n\nval calevScheduled = calevScheduler.awakeEvery(oddSeconds) \u003e\u003e printTime\n// calevScheduled: Stream[[x]IO[x], Unit] = Stream(..)\ncalevScheduled.take(3).compile.drain.unsafeRunSync()\n// 12:18:07.018297857\n// 12:18:09.000317064\n// 12:18:11.000249817\n```\n\n```scala\nval everyFourSeconds = CalEvent.unsafe(\"*-*-* *:*:0/4\")\n// everyFourSeconds: CalEvent = CalEvent(\n//   weekday = All,\n//   date = DateEvent(year = All, month = All, day = All),\n//   time = TimeEvent(\n//     hour = All,\n//     minute = All,\n//     seconds = List(values = Vector(Single(value = 0, rep = Some(value = 4))))\n//   ),\n//   zone = None\n// )\n\nval calevScheduledTasks = calevScheduler.schedule(List(\n  oddSeconds      -\u003e Stream.eval(IO(println(LocalTime.now.toString + \" task 1\"))),\n  everyFourSeconds -\u003e Stream.eval(IO(println(LocalTime.now.toString + \" task 2\")))\n))\n// calevScheduledTasks: Stream[IO, Unit] = Stream(..)\n\ncalevScheduledTasks.take(9).compile.drain.unsafeRunSync()\n// 12:18:12.000451379 task 2\n// 12:18:13.000994389 task 1\n// 12:18:15.000405413 task 1\n// 12:18:16.001177876 task 2\n// 12:18:17.001266828 task 1\n// 12:18:19.000612835 task 1\n// 12:18:20.000679117 task 2\n// 12:18:21.000881674 task 1\n// 12:18:23.000535002 task 1\n```\n\n## Using fs2-cron\n\nThe latest version of the library is available for Scala 2.12 and 2.13.\n\nIf you're using sbt, add the following to your build:\n```sbt\nlibraryDependencies ++= Seq(\n  \"eu.timepit\" %% \"fs2-cron-cron4s\" % \"0.10.2\" //and/or\n  \"eu.timepit\" %% \"fs2-cron-calev\" % \"0.10.2\"\n)\n```\n\n## License\n\n**fs2-cron** is licensed under the Apache License, Version 2.0, available at\nhttp://www.apache.org/licenses/LICENSE-2.0 and also in the\n[LICENSE](https://github.com/fthomas/status-page/blob/master/LICENSE) file.\n\n[Cron4s]: https://github.com/alonsodomin/cron4s\n[FS2]: https://github.com/functional-streams-for-scala/fs2\n[Calev]: https://github.com/eikek/calev\n","funding_links":[],"categories":["Scala","\u003ca name=\"Scala\"\u003e\u003c/a\u003eScala"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffthomas%2Ffs2-cron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffthomas%2Ffs2-cron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffthomas%2Ffs2-cron/lists"}