3

I want to change emacs default calendar week number so that it starts at a manually preset date. Normally the year is broken into 52 weeks and week 1 is the one that contains the 1st of January. I'd like to be able to either change this date to another, 20 of July (say), or to have a second week number that gets displayed when org-agenda is called. Like so

Week-agenda (W01):
Monday     20 July 2020 W01
Tuesday    21 July 2020
Wednesday  22 July 2020
Thursday   23 July 2020
Friday     24 July 2020
Saturday   25 July 2020
Sunday     26 July 2020

or

Week-agenda (W30 | W01):
Monday     20 July 2020 W30 | W01
Tuesday    21 July 2020
Wednesday  22 July 2020
Thursday   23 July 2020
Friday     24 July 2020
Saturday   25 July 2020
Sunday     26 July 2020

These are the closest posts that I could find so far link1 link2. I am using emacs 26.3 and org 9.2.6. This question is relevant because at my work place the week system is offset from the normal week system, and it would be great to be able to adjust emacs to it.

2 Answers 2

3

Looking at the souce code reveals that Org uses calendar functions to calculate that. You need to change calendar-iso-from-absolute.

Try the following modification, this will affect the calendar's week calculation and with that org-mode's. You can see the result, if you activate calendars week number view.

    (defun calendar-iso-from-absolute (date)
      (let* ((approx (calendar-extract-year
                      (calendar-gregorian-from-absolute (+ date 2))))
             (year (+ approx
                      (calendar-sum y approx
                                    (>= date (calendar-iso-to-absolute
                                              (list 1 1 (1+ y))))
                                    1)))
             (weekstart (calendar-absolute-from-gregorian (list 7 (+ 20 2) year))))
        (list
         (1+ (/ (- date (if (> weekstart date)
                            (calendar-absolute-from-gregorian (list 7 (+ 20 2) (- year 1)))
                          weekstart))
                7))
         (% date 7)
         year)))

The function above needs some minor tweaking to get it 100% correct.
I do not know why the date needs to be 3 days less, I just took it over from the approx calculation at the beginning of this function.

Of course you could also write an advice :after for the function above and then modify the car of its result list.

Edit to answer comment: to activate it from within your init, this function needs to be redefined, after the original version has been loaded. To do so you can put this new function definition in the :config part of (use-package cal-iso ...

    (use-package cal-iso
      :defer t
      :config
      (defun calendar-iso-from-absolute (date)
        ...
        )
      )

or you could use

(with-eval-after-load "cal-iso"
   (defun calendar-iso-from-absolute (date)
      ...
    ))

because calendar-iso-from-absolute is defined in file cal-iso.el.

Or, better yet, override it via advice (thanks to Basil). Note: you have to give your own function a different name.

(defun my-calendar-iso-from-absolute (date)
  ...
  )
(advice-add #'calendar-iso-from-absolute :override #'my-calendar-iso-from-absolute)
6
  • Thanks @jue. I've made some edits to change the month and the offset of number of days (had to be +2 for some reason). I think that this has to do with the definition of the ISO week date described in the function documentation. One question remains though... How can I activate the function in init.el? Probably because it is a compiled function it does not load automatically (i've got to do it manually).
    – Ajned
    Commented Dec 14, 2019 at 15:35
  • @Andre please see my edit
    – jue
    Commented Dec 16, 2019 at 10:00
  • 1
    Instead of redefining a function after its package has been loaded, I find it better to add an :override advice on the corresponding symbol using either define-advice or advice-add. This has several advantages: 1) the advice can be defined before its target function has been defined, i.e. at the top-level of your user-init-file; 2) the advice can easily be disabled and reenabled again, for debugging purposes; 3) the advice is listed in the *Help* buffer for its target function.
    – Basil
    Commented Dec 16, 2019 at 10:49
  • @Basil thanks, til
    – jue
    Commented Dec 16, 2019 at 12:23
  • 1
    BTW if you use the define-advice macro in Emacs 25+ (instead of the lower-level advice-add, it will generate the advice function name for you.
    – Basil
    Commented Dec 16, 2019 at 12:28
1

I'm afraid override calendar-iso-from-absolute is not a good idea, it will mess thing up. The line "Week-agenda (W01):" is generated by org-agenda-list, but it will generate something like "Week-agenda (W01-w04):" due to the different view (month view, for example). So this line is not suitable for modifying. The other line "Monday 11 April 2022 W15" is generated by org-agenda-format-date-aligned, it is suitable to attach additional information.

(defun org-days-to-relative-week (days-now days-start)
  "Compute weeks between two date.
DAYS-NOW and DAYS-START are both days from absolute gregorian"
  (1+ (/ (- days-now days-start) 7)))
(defun my-org-agenda-format-date-aligned (orig-fun date)
  (let ((day-of-week (calendar-day-of-week date))
    (custom-week (org-days-to-relative-week
              (calendar-absolute-from-gregorian date)
              (calendar-absolute-from-gregorian '(2 28 2002))))
    (orig-str (funcall orig-fun date)))
    (if (and custom-week (= 1 day-of-week))
    (format "%s | Week %02d" orig-str custom-week)
      orig-str)))
(advice-add 'org-agenda-format-date-aligned :around #'my-org-agenda-format-date-aligned)
1
  • Thanks, I've made some edits to your answer, as it was throwing an error out.
    – Ajned
    Commented Apr 13, 2022 at 7:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.