[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Extended example "3.2.3 Every second Sunday"

From: Felix Lechner
Subject: Extended example "3.2.3 Every second Sunday"
Date: Fri, 01 Dec 2023 09:14:47 -0800


Thanks for mcron! You maintain a cool and nifty program that dovetails
neatly with GNU Guix. I love it!

For some time, I have wondered about the example in Chapter 3.2.3 in the
manual. [1] It is suppposed to schedule "my-program" on the second
Sunday of every month:

    (job (lambda (current-time)
           (let* ((next-month (next-month-from current-time))
                  (first-day (tm:wday (localtime next-month)))
                  (second-sunday (if (eqv? first-day 0)
                                     (- 14 first-day))))
             (+ next-month (* 24 60 60 second-sunday))))

The manual also asks interested readers to think about how the code
works. Well, I loaded the code into a Guile REPL. I'm not sure it's
working the way I expect.

Today is December 1. My epoch right now is 1701448607. The lambda above
schedules the next run for epoch 1705219200. According to 'date -d
@1705219200' from GNU coreutils, that will be on January 14 of next

The way I see it, the example skips the second Sunday in December, which
is coming up on December 17.  More broadly, will the example ever
schedule a run in the current month?

Perhaps it only matters for equipment that reboots from time to time.

On my system, I use a more complicated strategy: To capture the next
appointment (below, for 1 AM) I calculate the time for the current month
as well as the time for the next month. I pick the appointment for next
month only when the present time is already past the appointment for
this month. I believe it's working.

Am I overthinking the issue? Thank you!

Kind regards
Felix Lechner

[1] https://www.gnu.org/software/mcron/manual/html_node/Every-second-Sunday.html

* * *
    (lambda (now)
      (let* ((second-sunday-in-month
              (lambda (timestamp)
                (let* ((day-of-month (tm:mday (localtime timestamp)))
                       (beginning-of-month (- timestamp (* 24 60 60 
                       (day-of-week (tm:wday (localtime beginning-of-month)))
                       (second-sunday-offset (if (eqv? 0 day-of-week)
                                                (- 14 day-of-week))))
                  (+ beginning-of-month (* 24 60 60 second-sunday-offset)))))
              (lambda (timestamp)
                (let ((second-sunday-morning (localtime (second-sunday-in-month 
                  (set-tm:hour second-sunday-morning 1)
                  (set-tm:min second-sunday-morning 0)
                  (set-tm:sec second-sunday-morning 0)
                  (car (mktime second-sunday-morning)))))
             (scheduled-this-month (scheduled-in-month now))
             (scheduled-next-month (scheduled-in-month (next-month-from now))))
        (if (< now scheduled-this-month)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]