262

In a Bash script, I want to print the current datetime in ISO 8601 format (preferably UTC), and it seems that this should be as simple as date -I:

http://ss64.com/bash/date.html

But this doesn't seem to work on my Mac:

$ date -I
date: illegal option -- I
usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... 
            [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]

And indeed, man date doesn't list this option.

Anyone know why this is, or any other (easy) way for me to print the date in ISO 8601 format? Thanks!

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Aseem Kishore
  • 10,404
  • 10
  • 51
  • 56
  • 2
    To clarify, I want a full ISO 8601 date, including the time, and preferably in UTC timezone. – Aseem Kishore Aug 27 '11 at 18:13
  • It's better to just edit the question. What format do you want the time in? – Tom Zych Aug 27 '11 at 18:16
  • @Tom: okay, edited. By format, is ISO 8601 not specific enough? – Aseem Kishore Aug 27 '11 at 18:22
  • No, ISO 8601 isn't specific enough. That standard specifies a number of formats of various precisions. Both `2011-08-27` and `2011-08-27T18:55:43Z` are ISO 8601 formats. And really, editing the question would be more helpful that scatting updates across several comments. An example of what you're trying to print would be ideal. – Keith Thompson Aug 27 '11 at 18:57
  • 10
    Having installed [GNU coreutils](http://www.gnu.org/software/coreutils) using [`brew`](http://brew.sh/) (which uses the prefix 'g') `gdate -I` did work, along with other GNU flags. – Joel Purra Dec 17 '13 at 08:46
  • 1
    @JoelPurra: It would be good to post your comment as an answer; I'd upvote it. – codermonkeyfuel Sep 01 '16 at 14:34
  • @codermonkeyfuel: [@slm beat me to it](http://stackoverflow.com/a/38856066/907779) ;) – Joel Purra Sep 02 '16 at 16:46
  • SS64 has a MacOS page which covers this https://ss64.com/osx/date.html – SS64 Feb 19 '21 at 12:51

10 Answers10

426

You could use

date "+%Y-%m-%d"

Or for a fully ISO-8601 compliant date, use one of the following formats:

date -u +"%Y-%m-%dT%H:%M:%SZ"

Output:

2011-08-27T23:22:37Z

or

date +%Y-%m-%dT%H:%M:%S%z

Output:

2011-08-27T15:22:37-0800
Matt Kantor
  • 1,704
  • 1
  • 19
  • 37
amit_g
  • 30,880
  • 8
  • 61
  • 118
  • 7
    Technically, the "T" is recommended but optional in ISO 8601. Using a space instead of 'T' would be: date -u +"%Y-%m-%d %H-%M-%SZ" – Basil Bourque Aug 15 '13 at 06:10
  • Finally! I added this to my bash_alias – Christian Bongiorno Aug 26 '16 at 17:23
  • Yup, awesome answer Thanks!, but this `date -u +"%Y-%m-%dT%H:%MZ"` exactly I was looking for. – ChikuMiku Jan 07 '17 at 14:55
  • Why is the `Z` there? Ruby's [`#iso8601`](https://ruby-doc.org/stdlib-2.1.1/libdoc/time/rdoc/Time.html#method-c-iso8601) doesn't seem to have it: `ruby -e 'require "time"; puts Time.now.iso8601' #=> 2017-04-10T13:44:03-07:00` – mbigras Apr 10 '17 at 20:47
  • 3
    @mbigras : `Z` and `+00:00` are the same (mostly). For purposes of translating time, they both mean UTC. However England is `+00:00` in winter and `+01:00` in summer (BST). – Jeffrey Hulten May 10 '17 at 21:32
  • 8
    @JeffreyHulten: "they both mean UTC" - Nitpick, but `Z` is UTC, while `+00:00` is GMT. UTC is not a timezone and does not have an offset; offset is defined as the time difference between a timezone and UTC, the standard of time measurement. GMT is +00:00 removed from UTC (and BST is, as you say, +01:00 removed from UTC). – Amadan Jul 04 '18 at 09:54
  • BTW: Your solution is the most portable. I get identical results on mac and alpine and ubuntu – Christian Bongiorno Dec 02 '20 at 16:49
  • @BasilBourque, as you already mentioned, the `T` can be omitted, but not in _all_ cases. There are rare possibilities of ambiguity depending on the format you're using. Probably obvious but seemed worthy to note. As written on [Wikipedia](https://en.wikipedia.org/wiki/ISO_8601#Times), _"So a time might appear as either "T134730" in the basic format or "T13:47:30" in the extended format. ISO 8601-1:2019 allows the T to be omitted in the extended format, as in "13:47:30", but only allows the T to be omitted in the basic format when there is no risk of ambiguity with date expressions."_ – John Pancoast Oct 23 '21 at 19:08
  • 2
    I should add that, my previous comment was only referring to times in `ISO-8601-1:2019` format. When referring to combinations of date and time, the [Wiki page](https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations) says that separating date and time with a character other than `T` is no longer supported in `ISO-8601-1:2019` but it _is_ supported in its profile, [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339). In short, I'm just confusing things and it's generally fine to omit the T :) Just adding the details I noticed regarding the newer spec. – John Pancoast Oct 23 '21 at 19:49
72

In GNU date date -I is the same as date +%F, and -Iseconds and -Iminutes also include time with UTC offset.

$ date +%F # -I or +%Y-%m-%d
2013-05-03
$ date +%FT%T%z # -Iseconds or +%Y-%m-%dT%H:%M:%S%z
2013-05-03T15:59:24+0300
$ date +%FT%H:%M # -Iminutes or +%Y-%m-%dT%H:%M%z
2013-05-03T15:59+0300

-u is like TZ=UTC. +00:00 can be replaced with Z.

$ date -u +%FT%TZ
2013-05-03T12:59:24Z

These are also valid ISO 8601 date or time formats:

20130503T15 (%Y%m%dT%M)
2013-05 (%Y%m)
2013-W18 (%Y-W%V)
2013-W18-5 (%Y-W%V-%u)
2013W185 (%YW%V%u)
2013-123 (%Y-%j, ordinal date)
2013 (%Y)
1559 (%H%M)
15 (%H)
15:59:24+03 (UTC offset doesn't have to include minutes)

These are not:

2013-05-03 15:59 (T is required in the extended format)
201305 (it could be confused with the YYMMDD format)
20130503T15:59 (basic and exteded formats can't be mixed)
Lri
  • 26,768
  • 8
  • 84
  • 82
27

A short alternative that works on both GNU and BSD date is:

date -u +%FT%T%z
SomeGuy
  • 271
  • 3
  • 2
25

The coreutils package provides GNU versions of tools. To install:

$ brew install coreutils

You can see what's provided:

$ brew list coreutils

Notice it comes with date:

$ brew list coreutils | grep date

This is the standard GNU date command so it'll take the -I switch:

$ gdate -I
2016-08-09
popedotninja
  • 1,170
  • 1
  • 12
  • 23
slm
  • 15,396
  • 12
  • 109
  • 124
8

Just use normal date formatting options:

date '+%Y-%m-%d'

Edit: to include time and UTC, these are equivalent:

date -u -Iseconds

date -u '+%Y-%m-%dT%k:%M:%S%z'
Tom Zych
  • 13,329
  • 9
  • 36
  • 53
  • Added a comment to my OP clarifying that I want the full date, including the time, and preferably in UTC timezone. Thanks for the tip, though! – Aseem Kishore Aug 27 '11 at 18:15
4

Taking the other answers one step further, you could add a function to your ~/.bashrc or ~/.zshrc to add the date -I flag:

date() {
  if [ "$1" = "-I" ]; then
    command date "+%Y-%m-%dT%H:%M:%S%z"
  else
  command date "$@"
  fi
}
ruby_slinger
  • 111
  • 3
3

It's not a feature of Bash, it's a feature of the date binary. On Linux you would typically have the GNU coreutils version of date, whereas on OSX you would have the BSD legacy utilities. The GNU version can certainly be installed as an optional package, or you can roll your own replacement - I believe it should be a simple one-liner e.g. in Perl.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Interesting, thanks. I'm kind of a Mac/Linux/Unix/Bash noob; would you mind elaborating on coreutils and how to install it on Mac? Thanks! – Aseem Kishore Aug 27 '11 at 18:16
2

There's a precompiled coreutils package for Mac OS X available at:

http://rudix.org/packages-abc.html#coreutils.

tonyk
  • 29
  • 1
1

So many years later, but in macOS 12 (Monterey) man date does include the -I option, but it generates the same error, unless you dig further and find

 date -u -I seconds
2023-08-04T03:59:20+00:00

I note that it doesn't append "Z" to the end, but the -u option did make it output in UTC.

Ian Green
  • 31
  • 5
0

I regularly use 'date -I' in Linux when saving files. ex: touch x.date -I. While the equivalent in MacOS is 'date +%F', it is a bit awkward to type every time I save a file. So, I set an alias "alias dt='date +%F'" then touch x.dt gives me the date.