4

I can make some date arithmetic with date command like

$ date -u -d '3 days 2024-12-01T00:00:00Z' +%FT%H:%M:%SZ
2024-12-04T00:00:00Z
$

The date command can parse quite a lot of date formats, including ISO-8601 formats. Is there an easy way to make it to interpret also ISO-8601 intervals? Naive approach fails...

$ date -u -d 'PT3D 2024-12-01T00:00:00Z' +%FT%H:%M:%SZ
date: invalid date ‘PT3D 2024-12-01T00:00:00Z’
$
5
  • Thank you! I saw that Q&A. It has nothing about intervals... Commented Dec 2, 2024 at 7:38
  • That 2024-12-04T05:00:00Z result for your first command looks bogus. With -u and GNU date I'd expect 2024-12-04T00:00:00Z Commented Dec 2, 2024 at 8:24
  • Fixed! Thank you! Commented Dec 2, 2024 at 8:27
  • Shouldn’t it read 2024-12-01T00:00:00Z/P3D (no T and and period after the reference date separated with a /)? Commented Dec 2, 2024 at 16:02
  • If I got it right 2024-12-01T00:00:00Z/P3D means interval of times. The goal was to add time and duration and get time as the result. en.wikipedia.org/wiki/ISO_8601 Commented Dec 3, 2024 at 9:38

1 Answer 1

5

The standard date utility doesn't support a -d option. There are a few implementations that do, but sometimes for completely different things.

Several of them (including some BSDs now even though they have their own different syntax for that) have a -d to specify an input date as opposed to take the system clock, following GNU date's lead, but the input format(s) they recognise is different between them. Some of them allow specifying the input format in strptime() fashion (ast-open, busybox, toybox), others don't (GNU, NetBSD¹).

Among the date implementations that support -d to specify an input date, I know of only ast-open's (AT&T Software Technology from AT&T Research formerly known as Bell Labs where Unix was born) that supports ISO8601 durations. But ast-open is no longer maintained AFAIK.

However ksh93, which uses the same date manipulation library is still maintained, and you can use its printf builtin to do the equivalent of GNU date -d:

$ TZ=UTZ0 printf '%(%FT%TZ)T\n' '2024-12-01T00:00:00Z PT3D'
2024-12-04T00:00:00Z

Beware that its DST handling when it comes to date calculation is still quite buggy, though that doesn't apply for UTC dates.

To make it a function to be used in another Bourne-like shell:

iso_add_time() { # args: <duration> <datetime> [<datetime>...]
  ksh93 -c '
    duration=${1?}; shift
    for date do
      TZ=UTC0 printf "%(%FT%TZ)T\n" "$date $duration" || exit
    done' ksh93 "$@"
}

¹ Though NetBSD's like other BSD's allow specifying the input format if using the BSD style way to specify the input date.

2
  • Thank you for detailed and well-grounded answer. Using ksh93 for my purpose is a bit of an overkill, but it is good to know about such an option. Commented Dec 2, 2024 at 7:44
  • Looks like a workable option. $ TZ=UTZ0 ksh -c "printf '%(%FT%TZ)T' '2024-12-01T00:00:00Z PT3D'" One just has not to get lost in quotes :) Thanks again! Commented Dec 2, 2024 at 8:23

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.