0

I am trying to iterate day-wise over a specified time range. That is, applying an operation to a time interval that starts at 00:00 the current day and ends at 00:00 the following day. For this, I am trying to add a one day offset to a given timestamp.

The issue I am running into is that adding 24 hours to a timestamp of course does not take daylight savings into account.

Problem:

2024-09-30 Mon 00:00 Europe/Berlin + 24h gives me the timestamp of 00:00 the following day. But 2024-10-27 Sun 00:00 Europe/Berlin + 24h results with 23:00 the same day, since the 27th has 25 hours due to change in daylight savings time.

Intended outcome:

I would like to result with the timestamp of one day later, taking daylight savings into account. On days that are affected by daylight savings, this results to adding 23h or 25h.

elisp code (org):

#+begin_src emacs-lisp (format-time-string "%Y-%m-%d %a %H:%M %z" (time-add (seconds-to-time (org-matcher-time "<2024-09-30 Mon 00:00 Europe/Berlin>")) (date-to-time "1970-01-02T00:00Z Europe/Berlin"))) ;; 24h #+end_src #+RESULTS: : 2024-10-01 Tue 00:00 +0200 #+begin_src emacs-lisp (format-time-string "%Y-%m-%d %a %H:%M %z" (time-add (seconds-to-time (org-matcher-time "<2024-10-27 Sun 00:00 Europe/Berlin>")) (date-to-time "1970-01-02T00:00Z Europe/Berlin"))) ;; 24h #+end_src #+RESULTS: : 2024-10-27 Sun 23:00 +0100 

Other approaches: I went over the possibility of converting to the number of days via (date-to-day "2024-09-30 Mon 00:00 Europe/Berlin"), and simply adding 1 to bypass the underlying time resolution, but it seems there is no simple way to get back to timestamps.

2
  • emacs.stackexchange.com/tags/elisp/info Commented Feb 7 at 16:58
  • 1
    What are you planning to do with the resulting time stamp? If you want a time stamp with 00:00 as the time, then the easiest thing to do is to add 1 day to the date part and just tack on the 00:00 at the end. That avoids a world of hurt. Commented Feb 7 at 20:22

1 Answer 1

1

I managed to come up with a solution for my case:

(defun seconds-add-n-days-midnight(now days) (let ((now-time (decode-time (seconds-to-time now)))) (setf (elt now-time 3) (+ (elt now-time 3) days) ; move n days into the future (elt now-time 2) '0 ; force hour (elt now-time 1) '0) ; and minute to zero) (time-to-seconds (encode-time now-time)))) (seconds-add-n-days-midnight (org-matcher-time "<2024-09-30 Mon 00:00 Europe/Berlin>") 1) 

While I am sure this is not the best solution, just adding one to the day manually and re-encoding the time handles the wrap-around in month or year. Not sure why I got stuck so badly on this one. Thanks @NickD!

1
  • "Not sure why I got stuck so badly on this one" : time calculations are almost never easy and the Emacs API is confusing; bringing in daylight savings time and different time zones just makes an already difficult situation almost impossible... Commented Feb 10 at 17:35

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.