emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Diary sexp and comparing dates, agenda
@ 2024-01-12  5:58 David Rogers
  2024-01-12 17:01 ` Tory S. Anderson
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: David Rogers @ 2024-01-12  5:58 UTC (permalink / raw)
  To: Org-mode list

Hello all

I'm using the Org agenda to show when certain church occasions 
will happen. Mostly I've got them working correctly, after 
"stealing" the method used in holidays.el for finding the date of 
Easter, along with someone else's function that then uses that to 
find the difference between Easter and today. (I'm pretty sure 
that whole idea was on emacswiki, and I think Paul Sexton put it 
together.)

So now I have a much smaller problem to solve, but I don't 
understand how to get it to work; I suspect it has to do with how 
dates get formatted within different functions. Using what I 
already have, I can do this:

* Example 1
<%%(= 245 (mf-days-from-easter))>

because "mf-days-from-easter" is defined in my init file, along 
with the definition of Easter itself. This does what it looks like 
it should do; this year, Example 1 is shown on December 1.

And I can do

* Example 2
<%%(and (diary-float 1 0 5 7) (<= (mf-days-from-easter) -56))>

to say "five Sundays after January 6th, but only if Easter is 
still 8 weeks away or more".

But Example 1 isn't quite finished, because that date is too close 
to Christmas. I can easily show a diary sexp defining when "too 
close to Christmas" is:

<%%(diary-float 12 0 -4 24)>

So I want to combine these ideas, to say "Show Example 1 in the 
agenda 245 days after Easter each year, but only if it's earlier 
than the fourth Sunday before Christmas".

I could do a long string of (and (not this day, not this day, etc 
etc [insert long list of days] . . . , but that seems like a last 
resort.

Everything in this question fits into "the current year according 
to the agenda view" - there's no need to consider dates that cross 
a year boundary.

So: Is there a fairly simple way to define a (mf-days-from-advent) 
that will do a similar job to what (mf-days-from-easter) is 
already doing (i.e. it works when used in a diary sexp)?


Here are the relevant definitions I've been using:


    (defun mf-easter (displayed-year)
        (let* ((century (1+ (/ displayed-year 100)))
               (shifted-epact               ; age of moon for 
               April 5...
                (% (+ 14 (* 11 (% displayed-year 19)) ; ...by 
                Nicaean rule
                      (-     ; ...corrected for the Gregorian 
                      century rule
                       (/ (* 3 century) 4))
                      (/       ; ...corrected for Metonic cycle 
                      inaccuracy
                       (+ 5 (* 8 century)) 25)
                      (* 30 century))       ; keeps value positive
                   30))
               (adjusted-epact              ; adjust for 29.5 day 
               month
                (if (or (zerop shifted-epact)
                        (and (= shifted-epact 1) (< 10 (% 
                        displayed-year 19))))
                    (1+ shifted-epact)
                  shifted-epact))
               (paschal-moon ; day after the full moon on or after 
               March 21
                (- (calendar-absolute-from-gregorian (list 4 19 
                displayed-year))
                   adjusted-epact)))
               (calendar-dayname-on-or-before 0 (+ paschal-moon 
               7))))



    (defun mf-days-from-easter ()
      "When used in a diary sexp, this function will calculate how 
      many days
are between the current date (DATE) and Easter Sunday."
      (- (calendar-absolute-from-gregorian date)
         (mf-easter (calendar-extract-year date))))


-- 
David


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Diary sexp and comparing dates, agenda
  2024-01-12  5:58 Diary sexp and comparing dates, agenda David Rogers
@ 2024-01-12 17:01 ` Tory S. Anderson
  2024-01-12 18:11 ` Ken Mankoff
  2024-01-12 23:00 ` Ihor Radchenko
  2 siblings, 0 replies; 7+ messages in thread
From: Tory S. Anderson @ 2024-01-12 17:01 UTC (permalink / raw)
  To: Org-mode list

I don't have an answer -- my own use of diary-sexp is nothing more than standard holiday inclusion -- but I'm interested and watching for answers on the list. I personally didn't know that you could do such calculations the way you are, such as "too close to DATE", so I'm impressed!

- Tory


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Diary sexp and comparing dates, agenda
  2024-01-12  5:58 Diary sexp and comparing dates, agenda David Rogers
  2024-01-12 17:01 ` Tory S. Anderson
@ 2024-01-12 18:11 ` Ken Mankoff
  2024-01-12 23:00 ` Ihor Radchenko
  2 siblings, 0 replies; 7+ messages in thread
From: Ken Mankoff @ 2024-01-12 18:11 UTC (permalink / raw)
  To: David Rogers; +Cc: emacs-orgmode

Hi David,

I'm not sure if this will help, but I have to file time sheets on the last weekday less than or equal to the 15th and last-day-of-month.

I wrote two diary functions to achieve this (I don't handle holiday edge cases). I use these functions with:

** INFO [#A] Time Sheet
<%%(kdm/diary-last-weekday-of-month date)>
<%%(kdm/diary-last-weekday-15th date)>

Functions are:

(defun kdm/diary-last-weekday-15th (date)
  (let* (
	 (dow (calendar-day-of-week date))
	 (dom (calendar-extract-day date))
	 (weekday (and (>= dow 1) (<= dow 5))))
    (or 
     (and weekday (= dom 15))
     (and (= dow 5) (= dom 14))
     (and (= dow 5) (= dom 13)))))

(defun kdm/diary-last-weekday-of-month (date)
  (let* (
	 (dow (calendar-day-of-week date))
	 (dom (calendar-extract-day date))
         (month (calendar-extract-month date))
         (year (calendar-extract-year date))
         (ldom-num (calendar-last-day-of-month month year))
	 (weekday (and (>= dow 1) (<= dow 5))))
    (or 
     (and weekday (= dom ldom-num))
     (and (= dow 5) (= (+ 1 dom) ldom-num))
     (and (= dow 5) (= (+ 2 dom) ldom-num)))))

  -k.

On 2024-01-11 at 21:58 -08, David Rogers <davidandrewrogers@gmail.com>
wrote...
> Hello all
>
> I'm using the Org agenda to show when certain church occasions will
> happen. Mostly I've got them working correctly, after "stealing" the
> method used in holidays.el for finding the date of Easter, along with
> someone else's function that then uses that to find the difference
> between Easter and today. (I'm pretty sure that whole idea was on
> emacswiki, and I think Paul Sexton put it together.)
>
> So now I have a much smaller problem to solve, but I don't understand
> how to get it to work; I suspect it has to do with how dates get
> formatted within different functions. Using what I already have, I can
> do this:
>
> * Example 1 <%%(= 245 (mf-days-from-easter))>
>
> because "mf-days-from-easter" is defined in my init file, along with
> the definition of Easter itself. This does what it looks like it
> should do; this year, Example 1 is shown on December 1.
>
> And I can do
>
> * Example 2 <%%(and (diary-float 1 0 5 7) (<= (mf-days-from-easter)
> -56))>
>
> to say "five Sundays after January 6th, but only if Easter is still 8
> weeks away or more".
>
> But Example 1 isn't quite finished, because that date is too close to
> Christmas. I can easily show a diary sexp defining when "too close to
> Christmas" is:
>
> <%%(diary-float 12 0 -4 24)>
>
> So I want to combine these ideas, to say "Show Example 1 in the agenda
> 245 days after Easter each year, but only if it's earlier than the
> fourth Sunday before Christmas".
>
> I could do a long string of (and (not this day, not this day, etc etc
> [insert long list of days] . . . , but that seems like a last resort.
>
> Everything in this question fits into "the current year according to
> the agenda view" - there's no need to consider dates that cross a year
> boundary.
>
> So: Is there a fairly simple way to define a (mf-days-from-advent)
> that will do a similar job to what (mf-days-from-easter) is already
> doing (i.e. it works when used in a diary sexp)?
>
>
> Here are the relevant definitions I've been using:
>
>
>    (defun mf-easter (displayed-year)
>        (let* ((century (1+ (/ displayed-year 100)))
>               (shifted-epact ; age of moon for April 5...
>                (% (+ 14 (* 11 (% displayed-year 19)) ; ...by Nicaean
>                rule
>                      (- ; ...corrected for the Gregorian century rule
>                       (/ (* 3 century) 4)) (/ ; ...corrected for
>                      Metonic cycle inaccuracy
>                       (+ 5 (* 8 century)) 25) (* 30 century)) ; keeps
>                      value positive
>                   30)) (adjusted-epact ; adjust for 29.5 day month
>                (if (or (zerop shifted-epact)
>                        (and (= shifted-epact 1) (< 10 (%
>                       displayed-year 19))))
>                    (1+ shifted-epact) shifted-epact))
>               (paschal-moon ; day after the full moon on or after
>               March 21
>                (- (calendar-absolute-from-gregorian (list 4 19
>                displayed-year))
>                   adjusted-epact))) (calendar-dayname-on-or-before 0
>               (+ paschal-moon 7))))
>
>
>
>    (defun mf-days-from-easter ()
>      "When used in a diary sexp, this function will calculate how many
> days are between the current date (DATE) and Easter Sunday."
>      (- (calendar-absolute-from-gregorian date)
>         (mf-easter (calendar-extract-year date))))



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Diary sexp and comparing dates, agenda
  2024-01-12  5:58 Diary sexp and comparing dates, agenda David Rogers
  2024-01-12 17:01 ` Tory S. Anderson
  2024-01-12 18:11 ` Ken Mankoff
@ 2024-01-12 23:00 ` Ihor Radchenko
  2024-01-13  5:41   ` David Rogers
  2 siblings, 1 reply; 7+ messages in thread
From: Ihor Radchenko @ 2024-01-12 23:00 UTC (permalink / raw)
  To: David Rogers; +Cc: Org-mode list

David Rogers <davidandrewrogers@gmail.com> writes:

> * Example 1
> <%%(= 245 (mf-days-from-easter))>
>
> because "mf-days-from-easter" is defined in my init file, along 
> with the definition of Easter itself. This does what it looks like 
> it should do; this year, Example 1 is shown on December 1.
>
> And I can do
>
> * Example 2
> <%%(and (diary-float 1 0 5 7) (<= (mf-days-from-easter) -56))>
>
> to say "five Sundays after January 6th, but only if Easter is 
> still 8 weeks away or more".
>
> But Example 1 isn't quite finished, because that date is too close 
> to Christmas. I can easily show a diary sexp defining when "too 
> close to Christmas" is:
>
> <%%(diary-float 12 0 -4 24)>
>
> So I want to combine these ideas, to say "Show Example 1 in the 
> agenda 245 days after Easter each year, but only if it's earlier 
> than the fourth Sunday before Christmas".

You don't need diary-float - it returns true/false whether current DATE
fits the arguments.

Instead, you can make use of `calendar-nth-named-absday'.
For example,

<%%(and (= 245 (mf-days-from-easter))
        (< (calendar-absolute-from-gregorian date)
           (calendar-nth-named-absday -4 0 12 24)))>

Diary sexps are nothing but ordinary Elisp, with an extra twist that
during evaluation `date' variable is bound to current calendar date.
When they return nil, DATE does not match.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Diary sexp and comparing dates, agenda
  2024-01-12 23:00 ` Ihor Radchenko
@ 2024-01-13  5:41   ` David Rogers
  2024-01-13 20:05     ` Ihor Radchenko
  0 siblings, 1 reply; 7+ messages in thread
From: David Rogers @ 2024-01-13  5:41 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Org-mode list

Ihor Radchenko <yantar92@posteo.net> writes:

> You don't need diary-float - it returns true/false whether 
> current DATE
> fits the arguments.
>
> Instead, you can make use of `calendar-nth-named-absday'.
> For example,
>
> <%%(and (= 245 (mf-days-from-easter))
>         (< (calendar-absolute-from-gregorian date)
>            (calendar-nth-named-absday -4 0 12 24)))>
>
> Diary sexps are nothing but ordinary Elisp, with an extra twist 
> that
> during evaluation `date' variable is bound to current calendar 
> date.
> When they return nil, DATE does not match.


Thank you!

It seems that `calendar-nth-named-absday' wants the year after the 
month, and then an (optional) day of the month to count from. 
Since I hoped to keep re-using this material every year without 
re-entering the calculations, I've tried the following:

In my init file, I've added these two short definitions:

    (defun mf-beginning-of-advent (displayed-year)
      (calendar-nth-named-absday -4 0 12 displayed-year 24))

    (defun mf-days-from-advent ()
      (- (calendar-absolute-from-gregorian date) 
      (mf-beginning-of-advent (calendar-extract-year date))))

And my Org file has this:

* Example 1
<%%(and (= 245 (mf-days-from-easter)) (<= (mf-days-from-advent) 
-1))>


This setup seems to work so far. Does it look reasonable to you?

-- 
David


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Diary sexp and comparing dates, agenda
  2024-01-13  5:41   ` David Rogers
@ 2024-01-13 20:05     ` Ihor Radchenko
  2024-01-13 23:44       ` David Rogers
  0 siblings, 1 reply; 7+ messages in thread
From: Ihor Radchenko @ 2024-01-13 20:05 UTC (permalink / raw)
  To: David Rogers; +Cc: Org-mode list

David Rogers <davidandrewrogers@gmail.com> writes:

> This setup seems to work so far. Does it look reasonable to you?

Yes, but I may not be a reliable judge. I do not have a lot of practical
experience with diary sexps other than when people report Org mode bugs :)

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Diary sexp and comparing dates, agenda
  2024-01-13 20:05     ` Ihor Radchenko
@ 2024-01-13 23:44       ` David Rogers
  0 siblings, 0 replies; 7+ messages in thread
From: David Rogers @ 2024-01-13 23:44 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Org-mode list

Ihor Radchenko <yantar92@posteo.net> writes:

> David Rogers <davidandrewrogers@gmail.com> writes:
>
>> This setup seems to work so far. Does it look reasonable to 
>> you?
>
> Yes, but I may not be a reliable judge. I do not have a lot of 
> practical
> experience with diary sexps other than when people report Org 
> mode bugs :)

Since it looks not-stupid to you, and it gives the right answer, 
and if there WAS a mistake the risk of injuring anyone is . . . 
rather low :) , I'm declaring it good enough.

-- 
Thanks again
David


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-01-13 23:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-12  5:58 Diary sexp and comparing dates, agenda David Rogers
2024-01-12 17:01 ` Tory S. Anderson
2024-01-12 18:11 ` Ken Mankoff
2024-01-12 23:00 ` Ihor Radchenko
2024-01-13  5:41   ` David Rogers
2024-01-13 20:05     ` Ihor Radchenko
2024-01-13 23:44       ` David Rogers

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).