• cuu508 18 hours ago

    Looks well done. I like how the docs describe every syntax feature, and every non-standard feature in detail. Hat tip to implementing Vixie's "*,10" quirk, and to handling DST.

  • the_duke 11 hours ago

    There is also a cron parser library from Cloudflare which is used for their cron jobs: https://github.com/cloudflare/saffron

    • epage 13 hours ago

      After working with Jenkins which has "hashed value" support for automatic staggering of jobs, I think its essential in any cron syntax evaluater.

      • tison 13 hours ago

        This can be optionally supported. To be clear, does it mean almost "RANDOM at construction" and the parser will assign a value by a hash/random function and then the crontab struct has an immutable value of that field?

        • epage 10 hours ago

          The way jenkins did it is they took the job name and hashed that. This gives you good staggering while still being consistent from run to run (compared to using a random number). This does mean it is immutable, not just at construction but ideally across separate constructions so long as the seed is the same.

          For an API, I could see either taking in something that is hashable or just taking in a number and letting the caller choose their hashing. From the person's perspective writing cron syntax, they shouldn't care so long as they get the intended affect.

      • Black616Angel 17 hours ago

        Main drawback is the need for timestamps. Most crontab files or expressions I've seen didn't have them.

        • tison 16 hours ago

          If you mean timezone, I wrote an FAQ [1]: "Why does the crate require the timezone to be specified in the crontab expression?"

          [1] https://docs.rs/cronexpr/latest/cronexpr/#why-does-the-crate...

          • Denvercoder9 5 hours ago

            Requiring a timezone seems sensible to me, but I don't understand the choice to make it a required part of the expression, instead of a separate parameter. Most software specifies the timezone separately from the expression (e.g. k8s has separate `schedule` and `timezone` keys).

            • qwertox 13 hours ago

              Is `timezone` optional? I like it that it has the ability for one to provide it, but not providing it could just use the one the system has been configured to use.

              • tison 13 hours ago

                Yeah. Actually, this is possible to extend the interface with options to accept

                1. Optional Timezone.

                2. Second-level precision (perhaps feature flags are more suitable here)

                It just falls out my first requirements so I don't support it. Being too generic is a common source of failure in my experience.

                As a library developer I have my opinion on how things should be done and provide the default fits that mind :D

              • aaomidi 16 hours ago

                So many of these restrictions feels arbitrary. Not supporting comments? Why?

                Assuming UTC for tz is not weird and cron users expect it,

                I guess why even support this specific syntax if the crons need to be edited to fit how this code expects them? There may have been better options if you were going full green field.

                Good work though!

                • burntsushi 6 hours ago

                  > Assuming UTC for tz is not weird and cron users expect it,

                  That would definitely be weird and unexpected. My crons are interpreted with respect to my system's configured time zone, which seems way more expected than just using UTC.

                  Taking a datetime and just assuming it's UTC is often a mistake. It's why the TC39 Temporal proposal (overhauling datetimes for Javascript) won't let you silently do it.

                  • aaomidi 5 hours ago

                    Sure that’s an alternative too.

              • tison 16 hours ago

                Could you elaborate a bit on the issue? I'm not sure you are commenting on cronexpr or other libraries.

                In cronexpr, there is no requirement for a timestamp until you'd like to find the next scheduled time, and thus you need to provide a related point.

                To decouple with certain datetime lib, I made a `MakeTimestamp` struct which provides multiple constructors. Later, I found it somehow like a function overload :D

                • tricked 16 hours ago

                  Do you mean timezones? if so it shouldn't be that hard to detect if there's no timezone and add it with your own code.

                  • assiniboine 16 hours ago

                    It doesn't need timestamps. It parses crontab to/from timestamps where needed.

                  • 1oooqooq 9 hours ago

                    isn't cron removed from most distros? now you need 3 or 4 different files for systemd-cronie

                    • proaralyst 7 hours ago

                      Systemd timer units are usually two: one for the service you want to run, one for the timer file.

                      I think you're confusing systemd timer units with Cronie[0], a crond implementation that I think predates systemd? It's possible there's some systemd thing I don't know about though!

                      I think most distros at least have an installable crond

                      [0]: https://github.com/cronie-crond/cronie/

                      • encoderer an hour ago

                        Cron is still part of posix standard

                      • qwertox 14 hours ago

                        If you're into Python, APScheduler is the way to go.

                        It also has a cron scheduler [0] which includes scheduling down to seconds and perfectly integrates with asyncio [1].

                          async def myfunc():
                              print(f"\n{Fore.GREEN}Readout triggered at { datetime.now().strftime('%H:%M:%S') }{COLORS_RESET}\n")
                              await disk_temperatures_handler.readout(storage)
                          
                          scheduler = AsyncIOScheduler()
                          storage['scheduler'] = scheduler
                          
                          scheduler.add_job(myfunc, CronTrigger(second='*/15'), id='readout_job')
                          scheduler.start()
                        
                        You can also modify the interval on-the-fly.

                        [0] https://apscheduler.readthedocs.io/en/3.x/modules/triggers/c...

                        [1] https://apscheduler.readthedocs.io/en/3.x/modules/executors/...

                        • franga2000 4 hours ago

                          +1 for APScheduler, we've been running it in production in multiple apps for going on 4 years now without any issue that I can remember.

                        • faangguyindia 15 hours ago

                          I've LLM based crontab bot. Where I simply write stuff like "run my backupBitBuckettoDropbox.sh from home directory at 3am everyday".

                          I never really liked cronjob expressions.

                          • Jleagle 14 hours ago

                            This sounds great, if i could trust it to get it right 100% of the time.

                            • simonw 14 hours ago

                              With the right harness around it you could trust it. Set it up so that it takes your input, generates the cron expression, then uses a deterministic cron library to spit out a summary of what that expression does plus a list of next upcoming instances.

                              That should give you all the information you need to determine if it got the right expression.

                              • encoderer an hour ago

                                You think it would work to just pipe that description and next occurrences and ask an llm if it matches the intended prompt?

                                • simonw 29 minutes ago

                                  No, that still leaves a small probability of something weird happening - and since it's a small probability you might not ever spot it in your own testing.

                                  In this case I think it's better to run known, deterministic code that can turn a crontab into a clear explanation.