1

I am interested in inserting custom dates using the calendar, I found Insert date using a calendar which turned out to be quite useful. Org calendar : change date language? seems to have no effect (I would also like to avoid setting the variable via seq)

While this code works fine for English dates.

(defun my/org-insert-date-english ()
  "Insert a date at point using `org-read-date' with its optional argument
of TO-TIME so that the user can customize the date format more easily."
  (interactive)
  (require 'org)
  (let ((time (org-read-date nil 'to-time nil "Date:  ")))
    (insert (format-time-string "(W%W) (%a) %d %b %Y"
                                time))))

;; Inserts: (W19) (Thu) 16 May 2019

I was trying to modify it to get it work to insert dates in a different laguage than english.

My modifications below don't work but I am not sure why, could someone pin point what am I doing wrong?

(defun my/org-insert-date-german ()
  "Insert a date at point using `org-read-date' with its optional argument
of TO-TIME so that the user can customize the date format more easily."
  (interactive)
  (require 'org)
  (letf ((time (org-read-date nil 'to-time nil "Date:  "))
         (calendar-week-start-day 1)
         (calendar-day-name-array ["Montag" "Dienstag" "Mittwoch" "Donnerstag"
                                   "Freitag" "Samstag" "Sonntag"])
         (calendar-month-name-array ["Januar" "Februar" "März" "April" "Mai" "Juni"
                                     "Juli" "August" "September" "Oktober" "November"
                                     "Dezember"]))
    (insert (format-time-string "(KW%W) (%a) %d. %b %Y"
                                time))))

;; Inserts: (KW19) (Thu) 16. May 2019
;; Desired: (KW19) (Donnerstag) 16. Mai 2019

Notes: - Using Emacs 26.2

  • I don't think format-time-string works like that. Seems probable that it uses C functions that work based on the current locale. – Willy Lee May 16 at 19:12
  • That's the case, in the docs I could see format-time-string is a built-in function in ‘C source code’. but I couldn't come up with any workaround but jagrg answer does the trick – Cesc May 17 at 7:51
2

What you're trying to do won't work with format-time-string. Here's a time string formatter using calendar-* functions which you can use in place of format-time-string. I haven't thought about how the offsetting is done with calendar-week-start-day so for now you have to start the name array with "Sonntag".

(defun calendar-format-time-string (format-string time)
  (let* ((date (org-date-to-gregorian (format-time-string "%F" time)))
         (week (car (calendar-iso-from-absolute (time-to-days time))))
         (week-day (calendar-day-name date))
         (day (calendar-extract-day date))
         (month (calendar-month-name (calendar-extract-month date)))
         (year (calendar-extract-year date))
         (specs (format-spec-make ?W week ?a week-day ?d day ?b month ?Y year)))
    (format-spec format-string specs)))

Here's a more flexible approach which formats %B (January), %b (Jan), %A (Sunday), and %a (Sun) using calendar functions. All other specs are passed to format-time-string.

(defun calendar-format-time-string (format-string time)
  (let* ((case-fold-search nil)
         (date (org-date-to-gregorian (format-time-string "%F" time)))
         (week (calendar-day-name date))
         (week-abbrev (calendar-day-name date t))
         (month (calendar-month-name (calendar-extract-month date)))
         (month-abbrev (calendar-month-name (calendar-extract-month date) t))
         (specs (format-spec-make ?A week
                                  ?a week-abbrev
                                  ?B month
                                  ?b month-abbrev))
         time-string)
    (with-temp-buffer
      (insert format-string)
      (goto-char (point-min))
      (while (re-search-forward (mapconcat (lambda (char)
                                             (concat "%" (char-to-string char)))
                                           (mapcar #'car specs) "\\|")
                                 nil t)
         (let ((spec (format-spec (match-string 0) specs)))
           (delete-char -2)
           (insert spec)))
       (setq time-string (buffer-substring (point-min) (point-max))))
     (format-time-string time-string time)))

BTW you can also use format-time-string directly by changing the time locale:

  1. $ sudo emacs /etc/locale.gen
  2. uncomment the de_DE.UTF-8 UTF-8 line and save the file
  3. $ sudo locale-gen
  4. M-x set-locale-environment RET de_DE.UTF-8 RET
  5. restart emacs

Now set system-time-locale as a local variable and you're done:

(let ((system-time-locale "de_DE.UTF-8")
      (time (org-read-date nil 'to-time nil "Date:  ")))
  (insert (format-time-string "(KW%W) (%A) %d. %B %Y" time)))

;; => (KW19) (Samstag) 18. Mai 2019

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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