9

In a text document, while editing, I often need to increment/ decrement calendar data. So, Friday will need to become Monday, December will need to become March, etc.

Or 28 Apr after adding 5 will become 03 May, and even 31 Dec 2017 after adding 15 will become 15 Jan 2018.

Is there a way to achieve this by placing cursor on the desired word/ number and hitting some keys so that it increments or decrements?

So, while on Friday, I hit something to say 'Add 3' and it becomes Monday, etc. While on 28 in 28 Apr, I hit something to say 'Add 5' and it becomes 03 May. But while on Apr in 28 Apr, I hit something to say 'Subtract 2', it becomes 28 Feb, etc.

Just so that you get an idea, vim has a speeddating plugin that does exactly what I am aiming at.

NickD
  • 27,023
  • 3
  • 23
  • 42
deshmukh
  • 1,852
  • 13
  • 29
  • You could consider using org-mode to export to latex. https://orgmode.org/manual/LaTeX-export.html#LaTeX-export Then you are able to use org-mode's inbuilt shortcuts to increase their date specifications. https://orgmode.org/manual/Creating-timestamps.html#Creating-timestamps that's what I am doing anyway.. – Dieter.Wilhelm May 06 '18 at 11:00
  • This is not exactly what you're looking for and not a complete solution, but [calc](https://www.gnu.org/software/emacs/manual/html_mono/calc.html) can increment dates. For an overview, see https://nullprogram.com/blog/2009/06/23/ Using that and maybe something like [calc's Embedded Mode](https://www.gnu.org/software/emacs/manual/html_node/calc/Basic-Embedded-Mode.html) you might be able to whip something together that does just what you want. – izkon Nov 03 '18 at 03:18
  • Maybe https://github.com/xuchunyang/emacs-speeddating? – NickD May 21 '21 at 19:36

2 Answers2

1

Here's an example of how you can increment/decrement all ISO 8601 date strings in the current buffer by N days. M-x shift-dates will prompt you to enter the number of days to shift (enter a negative value to decrement). BTW I know this doesn't quite answer your question, but I think it's close.

(defun shift-date (date days)
  (format-time-string
   "%F"
   (time-add (time-to-seconds (days-to-time days))
             (time-to-seconds (org-time-string-to-time date)))))

(defun shift-dates (days)
  (interactive "nDays: ")
  (save-excursion
    (goto-char (point-min))
    (while (not (eobp))
      (forward-char 1)
      (when (looking-at iso8601--full-date-match)
        (let ((date (shift-date (match-string 0) days)))
          (save-excursion
            (while (looking-at "[^\s\\|\n]")
              (delete-char 1))
            (insert date)))))))
jagrg
  • 3,824
  • 4
  • 19
0

The answer uses calendar-day-name-array and calendar-month-name-array which are set by calendar.el and shipped with Emacs:

;; calendar-day-name-array ==> ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"]

;; calendar-month-name-array ==> ["January" "February" "May" "April" "May" "June" "July" "August" "September" "October" "November" "December"]

(require 'calendar)

(defun ar-shift--intern (arg thisarray)
    (let* ((name (substring-no-properties (word-at-point)))
       (bounds (bounds-of-thing-at-point 'word))
       (beg (car-safe bounds))
       (end (cdr-safe bounds))
       (counter 0)
       (laenge (length thisarray))
       (orig (point)) 
       idxr dlr
       (datelist (progn (while (< counter laenge)
                  (push (aref thisarray counter) dlr)
                  (setq counter (1+ counter)))
                (nreverse dlr)))
       (idx (progn
          (dolist (ele datelist)
            (unless idxr
              (when (string= ele name)
            (setq idxr counter))
              (setq counter (1+ counter))))
          idxr))
       (replaceform (aref thisarray
                  (if (< (+ arg idx) laenge)
                  (+ arg idx)
                (% (+ arg idx) laenge)))))
      (if (and beg end)
      (progn
        (delete-region beg end)
        (insert replaceform)
        (goto-char orig))
    (error "Don't see a date at point"))))

(defun ar-shift-day-atpt (arg)
   "Raise name of day at point ARG times.

Decrease with negative ARG"
   (interactive "p")
   (ar-shift--intern arg  calendar-day-name-array))

(defun ar-shift-month-atpt (arg)
  "Raise name of month at point ARG times.

Decrease with negative ARG"
  (interactive "p")
  (ar-shift--intern arg calendar-month-name-array))

Also raise or decrease positive integers: https://github.com/andreas-roehler/numbers-at-point

Andreas Röhler
  • 1,894
  • 10
  • 10