unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* The wild and weird world of Emacs Lisp date/time arithmetic
@ 2020-12-17 15:57 Skip Montanaro
  2020-12-17 19:23 ` Christopher Dimech
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Skip Montanaro @ 2020-12-17 15:57 UTC (permalink / raw)
  To: Help GNU Emacs

I have a very simple date calculation. I have a CSV file whose first field
is an ISO-8601 date, for example:

2020-12-03,738050,2262878,0.33

I want to write a function to add a day and append a new (empty) record.
The end result should look like this:

2020-12-03,738050,2262878,0.33
2020-12-04

Easy peasy, right? I have no problem plucking the time out of the buffer or
decoding the string. I'm having trouble converting back to string form
after parsing and doing the arithmetic. It seems to me that there are a
myriad number of datetime representations. I would have thought (based on
their names) that parse-time-string and format-time-string were
complementary functions, but they are not. This raises an exception:

(format-time-string "%Y-%m-%d" (parse-time-string "2020-05-17"))

So, given a timestamp as returned from (parse-time-string), how does one
format it for display? More concretely, I would like the return value from
this function:

(defun dt-convert ()
  (setq this-date (parse-time-string "2020-05-17"))
  (setq one-day (make-decoded-time :day 1))
  (setq next-date (decoded-time-add this-date one-day))
  (format-time-string "%Y-%m-%d" next-date)
  )

to be "2020-05-18".

Completely perplexed...

Skip Montanaro


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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 15:57 The wild and weird world of Emacs Lisp date/time arithmetic Skip Montanaro
@ 2020-12-17 19:23 ` Christopher Dimech
  2020-12-17 19:47 ` Teemu Likonen
  2020-12-18 15:37 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2 siblings, 0 replies; 8+ messages in thread
From: Christopher Dimech @ 2020-12-17 19:23 UTC (permalink / raw)
  To: Skip Montanaro; +Cc: Help GNU Emacs

> Sent: Thursday, December 17, 2020 at 4:57 PM
> From: "Skip Montanaro" <skip.montanaro@gmail.com>
> To: "Help GNU Emacs" <help-gnu-emacs@gnu.org>
> Subject: The wild and weird world of Emacs Lisp date/time arithmetic
>
> I have a very simple date calculation. I have a CSV file whose first field
> is an ISO-8601 date, for example:
>
> 2020-12-03,738050,2262878,0.33
>
> I want to write a function to add a day and append a new (empty) record.
> The end result should look like this:
>
> 2020-12-03,738050,2262878,0.33
> 2020-12-04
>
> Easy peasy, right? I have no problem plucking the time out of the buffer or
> decoding the string. I'm having trouble converting back to string form
> after parsing and doing the arithmetic. It seems to me that there are a
> myriad number of datetime representations. I would have thought (based on
> their names) that parse-time-string and format-time-string were
> complementary functions, but they are not. This raises an exception:
>
> (format-time-string "%Y-%m-%d" (parse-time-string "2020-05-17"))
>
> So, given a timestamp as returned from (parse-time-string), how does one
> format it for display? More concretely, I would like the return value from
> this function:
>
> (defun dt-convert ()
>   (setq this-date (parse-time-string "2020-05-17"))
>   (setq one-day (make-decoded-time :day 1))
>   (setq next-date (decoded-time-add this-date one-day))
>   (format-time-string "%Y-%m-%d" next-date)
>   )
>
> to be "2020-05-18".
>
> Completely perplexed...
>
> Skip Montanaro


I have had a similar experience working with dates.  It is problematic.




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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 15:57 The wild and weird world of Emacs Lisp date/time arithmetic Skip Montanaro
  2020-12-17 19:23 ` Christopher Dimech
@ 2020-12-17 19:47 ` Teemu Likonen
  2020-12-17 19:59   ` Teemu Likonen
  2020-12-17 20:04   ` Skip Montanaro
  2020-12-18 15:37 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2 siblings, 2 replies; 8+ messages in thread
From: Teemu Likonen @ 2020-12-17 19:47 UTC (permalink / raw)
  To: Skip Montanaro, Help GNU Emacs

[-- Attachment #1: Type: text/plain, Size: 814 bytes --]

* 2020-12-17 09:57:18-06, Skip Montanaro wrote:

> I want to write a function to add a day [...]

> I have no problem plucking the time out of the buffer or decoding the
> string. I'm having trouble converting back to string form after
> parsing and doing the arithmetic.

You can do it with a function like this:


    (defun my-add-one-day (date-string)
      (let ((decoded (decoded-time-add (parse-time-string date-string)
                                       (make-decoded-time :day 1))))
        (format "%04d-%02d-%02d"
                (nth 5 decoded)
                (nth 4 decoded)
                (nth 3 decoded))))


(my-add-one-day "2020-12-31") ;=> "2021-01-01"

-- 
/// Teemu Likonen - .-.. https://www.iki.fi/tlikonen/
// OpenPGP: 4E1055DC84E9DFF613D78557719D69D324539450

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 251 bytes --]

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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 19:47 ` Teemu Likonen
@ 2020-12-17 19:59   ` Teemu Likonen
  2020-12-17 20:04   ` Skip Montanaro
  1 sibling, 0 replies; 8+ messages in thread
From: Teemu Likonen @ 2020-12-17 19:59 UTC (permalink / raw)
  To: Skip Montanaro, Help GNU Emacs

[-- Attachment #1: Type: text/plain, Size: 979 bytes --]

* 2020-12-17 21:47:27+02, Teemu Likonen wrote:

>     (defun my-add-one-day (date-string)
>       (let ((decoded (decoded-time-add (parse-time-string date-string)
>                                        (make-decoded-time :day 1))))
>         (format "%04d-%02d-%02d"
>                 (nth 5 decoded)
>                 (nth 4 decoded)
>                 (nth 3 decoded))))

It's probably better to use access functions DECODED-TIME-YEAR etc.
instead of accessing list elements with NTH. So:

    (defun my-add-one-day (date-string)
      (let ((decoded (decoded-time-add (parse-time-string date-string)
                                       (make-decoded-time :day 1))))
        (format "%04d-%02d-%02d"
                (decoded-time-year decoded)
                (decoded-time-month decoded)
                (decoded-time-day decoded))))


-- 
/// Teemu Likonen - .-.. https://www.iki.fi/tlikonen/
// OpenPGP: 4E1055DC84E9DFF613D78557719D69D324539450

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 251 bytes --]

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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 19:47 ` Teemu Likonen
  2020-12-17 19:59   ` Teemu Likonen
@ 2020-12-17 20:04   ` Skip Montanaro
  2020-12-17 20:35     ` Stefan Möding
  1 sibling, 1 reply; 8+ messages in thread
From: Skip Montanaro @ 2020-12-17 20:04 UTC (permalink / raw)
  To: Teemu Likonen; +Cc: Help GNU Emacs

> You can do it with a function like this:
>
>     (defun my-add-one-day (date-string)
>       (let ((decoded (decoded-time-add (parse-time-string date-string)
>                                        (make-decoded-time :day 1))))
>         (format "%04d-%02d-%02d"
>                 (nth 5 decoded)
>                 (nth 4 decoded)
>                 (nth 3 decoded))))
>
> (my-add-one-day "2020-12-31") ;=> "2021-01-01"
>

Thanks. That isn't a problem in my case as my output format is dead simple.
Still, it seems there should be an inverse to parse-time-string which
consumes a format string and one of those n-element lists. I'm thinking in
terms of C stdio functions strptime and strftime, or the methods of the
same name for Python's datetime objects. That's what fooled me about the
format-time-string function. Its name implies that it would consume the
output of parse-time-string but it doesn't.

Skip


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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 20:04   ` Skip Montanaro
@ 2020-12-17 20:35     ` Stefan Möding
  2020-12-17 20:51       ` Skip Montanaro
  0 siblings, 1 reply; 8+ messages in thread
From: Stefan Möding @ 2020-12-17 20:35 UTC (permalink / raw)
  To: help-gnu-emacs

Skip Montanaro <skip.montanaro@gmail.com> writes:

> Still, it seems there should be an inverse to parse-time-string which
> consumes a format string and one of those n-element lists. I'm thinking in
> terms of C stdio functions strptime and strftime, or the methods of the
> same name for Python's datetime objects. That's what fooled me about the
> format-time-string function. Its name implies that it would consume the
> output of parse-time-string but it doesn't.

`format-time-string’ seems to use Lisp timestamps which can be created
with `encode-time’.  The following seems to solve your initial problem:

(format-time-string
 "%Y-%m-%d"
 (encode-time (decoded-time-add (parse-time-string "2020-05-17")
                                (make-decoded-time :day 1))))


Yes, it probably should be easier to do...

-- 
Stefan



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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 20:35     ` Stefan Möding
@ 2020-12-17 20:51       ` Skip Montanaro
  0 siblings, 0 replies; 8+ messages in thread
From: Skip Montanaro @ 2020-12-17 20:51 UTC (permalink / raw)
  To: Stefan Möding; +Cc: Help GNU Emacs

> `format-time-string’ seems to use Lisp timestamps which can be created
> with `encode-time’.  The following seems to solve your initial problem:
>
> (format-time-string
>  "%Y-%m-%d"
>  (encode-time (decoded-time-add (parse-time-string "2020-05-17")
>                                 (make-decoded-time :day 1))))

Thanks, yes, I just hit on that as well. Now to actually use this
knowledge before I forget it... :-)

Skip



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

* Re: The wild and weird world of Emacs Lisp date/time arithmetic
  2020-12-17 15:57 The wild and weird world of Emacs Lisp date/time arithmetic Skip Montanaro
  2020-12-17 19:23 ` Christopher Dimech
  2020-12-17 19:47 ` Teemu Likonen
@ 2020-12-18 15:37 ` Emanuel Berg via Users list for the GNU Emacs text editor
  2 siblings, 0 replies; 8+ messages in thread
From: Emanuel Berg via Users list for the GNU Emacs text editor @ 2020-12-18 15:37 UTC (permalink / raw)
  To: help-gnu-emacs

Skip Montanaro wrote:

> I have a very simple date calculation. I have a CSV file whose first field
> is an ISO-8601 date, for example:
>
> 2020-12-03,738050,2262878,0.33
>
> I want to write a function to add a day and append a new
> (empty) record. [...]

Slightly OT but this is some I have on the time subject:

  https://dataswamp.org/~incal/emacs-init/time-cmp.el

-- 
underground experts united
http://user.it.uu.se/~embe8573
https://dataswamp.org/~incal




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

end of thread, other threads:[~2020-12-18 15:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-12-17 15:57 The wild and weird world of Emacs Lisp date/time arithmetic Skip Montanaro
2020-12-17 19:23 ` Christopher Dimech
2020-12-17 19:47 ` Teemu Likonen
2020-12-17 19:59   ` Teemu Likonen
2020-12-17 20:04   ` Skip Montanaro
2020-12-17 20:35     ` Stefan Möding
2020-12-17 20:51       ` Skip Montanaro
2020-12-18 15:37 ` Emanuel Berg via Users list for the GNU Emacs text editor

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).