dotfile snippets: easily list `date` formatting and format strings on macOS (and linux)

I don't like fiddling around typing out date formats when I'm working – who does? I found this snippet a while ago. Unfortunately, I don't remember where anymore. I would love to credit the person who I copied this from, so let me know if you find it!

macOS

This is a bit cheaty because it doesn't use macOS's built-in date. For uniformity, since I work on both macOS and Linux a lot, I just use GNU's tools. For example, date is provided through coreutils, which can be installed through Brew:

brew install coreutils  

This should, by default, add gdate to your $PATH (all GNU commands are prefixed with g to not conflict with the built-in macOS commands).

In ~/.zshrc:

dates() {

cat << EOD  
        Format/result               |       Command               |          Output
------------------------------------+-----------------------------+------------------------------
YYYY-MM-DD_hh:mm:ss                 | gdate +%F_%T                | $(gdate +%F_%T)  
YYYYMMDD_hhmmss                     | gdate +%Y%m%d_%H%M%S        | $(gdate +%Y%m%d_%H%M%S)  
YYYYMMDD_hhmmss (UTC version)       | gdate --utc +%Y%m%d_%H%M%SZ | $(gdate --utc +%Y%m%d_%H%M%SZ)  
YYYYMMDD_hhmmss (with local TZ)     | gdate +%Y%m%d_%H%M%S%Z      | $(gdate +%Y%m%d_%H%M%S%Z)  
YYYYMMDD_Thhmmss (with num TZ) *    | gdate +%Y%m%d_T%H%M%S%z     | $(gdate +%Y%m%d_T%H%M%S%z)  
YYYYMMSShhmmss                      | gdate +%Y%m%d%H%M%S         | $(gdate +%Y%m%d%H%M%S)  
YYYYMMSShhmmssnnnnnnnnn             | gdate +%Y%m%d%H%M%S%N       | $(gdate +%Y%m%d%H%M%S%N)  
YYMMDD_hhmmss                       | gdate +%y%m%d_%H%M%S        | $(gdate +%y%m%d_%H%M%S)  
Seconds since UNIX epoch:           | gdate +%s                   | $(gdate +%s)  
Nanoseconds only:                   | gdate +%N                   | $(gdate +%N)  
Nanoseconds since UNIX epoch:       | gdate +%s%N                 | $(gdate +%s%N)  
ISO8601 UTC timestamp               | gdate --utc +%FT%TZ         | $(gdate --utc +%FT%TZ)  
ISO8601 UTC timestamp + ms          | gdate --utc +%FT%T.%3NZ     | $(gdate --utc +%FT%T.%3NZ)  
ISO8601 Local TZ timestamp          | gdate +%FT%T%Z              | $(gdate +%FT%T%Z)  
YYYY-MM-DD (Short day)              | gdate +%F\(%a\)             | $(gdate +%F\(%a\))  
YYYY-MM-DD (Long day)               | gdate +%F\(%A\)             | $(gdate +%F\(%A\))  
"ISO8601"-ish timestamp + w/        | gdate +%F_T%H-%M-%S%z       | $(gdate +%F_T%H-%M-%S%z)
  numerical timezone                |                             |
YYYYMMDD_hhmmss (with local TZ)     | gdate +%F_T%H%M%S%z         | $(gdate +%F_T%H-%M-%S%z)  
  numerical timezone (no dash)      |                             |

Notes:  
* use this for filenames 
EOD  
}

On Linux you just use date instead of gdate:

dates() {

cat << EOD  
        Format/result               |       Command               |          Output
------------------------------------+-----------------------------+------------------------------
YYYY-MM-DD_hh:mm:ss                 | date +%F_%T                | $(date +%F_%T)  
YYYYMMDD_hhmmss                     | date +%Y%m%d_%H%M%S        | $(date +%Y%m%d_%H%M%S)  
YYYYMMDD_hhmmss (UTC version)       | date --utc +%Y%m%d_%H%M%SZ | $(date --utc +%Y%m%d_%H%M%SZ)  
YYYYMMDD_hhmmss (with local TZ)     | date +%Y%m%d_%H%M%S%Z      | $(date +%Y%m%d_%H%M%S%Z)  
YYYYMMDD_Thhmmss (with num TZ) *    | date +%Y%m%d_T%H%M%S%z     | $(date +%Y%m%d_T%H%M%S%z)  
YYYYMMSShhmmss                      | date +%Y%m%d%H%M%S         | $(date +%Y%m%d%H%M%S)  
YYYYMMSShhmmssnnnnnnnnn             | date +%Y%m%d%H%M%S%N       | $(date +%Y%m%d%H%M%S%N)  
YYMMDD_hhmmss                       | date +%y%m%d_%H%M%S        | $(date +%y%m%d_%H%M%S)  
Seconds since UNIX epoch:           | date +%s                   | $(date +%s)  
Nanoseconds only:                   | date +%N                   | $(date +%N)  
Nanoseconds since UNIX epoch:       | date +%s%N                 | $(date +%s%N)  
ISO8601 UTC timestamp               | date --utc +%FT%TZ         | $(date --utc +%FT%TZ)  
ISO8601 UTC timestamp + ms          | date --utc +%FT%T.%3NZ     | $(date --utc +%FT%T.%3NZ)  
ISO8601 Local TZ timestamp          | date +%FT%T%Z              | $(date +%FT%T%Z)  
YYYY-MM-DD (Short day)              | date +%F\(%a\)             | $(date +%F\(%a\))  
YYYY-MM-DD (Long day)               | date +%F\(%A\)             | $(date +%F\(%A\))  
"ISO8601"-ish timestamp + w/        | date +%F_T%H-%M-%S%z       | $(date +%F_T%H-%M-%S%z)
  numerical timezone                |                            |
YYYYMMDD_hhmmss (with local TZ)     | date +%F_T%H%M%S%z         | $(date +%F_T%H-%M-%S%z)  
  numerical timezone (no dash)     

EOD  
}

Example output:

        Format/result               |       Command               |          Output
------------------------------------+-----------------------------+------------------------------
YYYY-MM-DD_hh:mm:ss                 | gdate +%F_%T                | 2025-02-01_15:30:00  
YYYYMMDD_hhmmss                     | gdate +%Y%m%d_%H%M%S        | 20250201_153000  
YYYYMMDD_hhmmss (UTC version)       | gdate --utc +%Y%m%d_%H%M%SZ | 20250201_233000Z  
YYYYMMDD_hhmmss (with local TZ)     | gdate +%Y%m%d_%H%M%S%Z      | 20250201_153000PST  
YYYYMMDD_Thhmmss (with num TZ) *    | gdate +%Y%m%d_T%H%M%S%z     | 20250201_T153000-0800  
YYYYMMSShhmmss                      | gdate +%Y%m%d%H%M%S         | 20250201153000  
YYYYMMSShhmmssnnnnnnnnn             | gdate +%Y%m%d%H%M%S%N       | 20250201153000726647000  
YYMMDD_hhmmss                       | gdate +%y%m%d_%H%M%S        | 250201_153000  
Seconds since UNIX epoch:           | gdate +%s                   | 1738452600  
Nanoseconds only:                   | gdate +%N                   | 734241000  
Nanoseconds since UNIX epoch:       | gdate +%s%N                 | 1738452600737131000  
ISO8601 UTC timestamp               | gdate --utc +%FT%TZ         | 2025-02-01T23:30:00Z  
ISO8601 UTC timestamp + ms          | gdate --utc +%FT%T.%3NZ     | 2025-02-01T23:30:00.741Z  
ISO8601 Local TZ timestamp          | gdate +%FT%T%Z              | 2025-02-01T15:30:00PST  
YYYY-MM-DD (Short day)              | gdate +%F\(%a\)             | 2025-02-01(Sat)  
YYYY-MM-DD (Long day)               | gdate +%F\(%A\)             | 2025-02-01(Saturday)  
"ISO8601"-ish timestamp + w/        | gdate +%F_T%H-%M-%S%z       | 2025-02-01_T15-30-00-0800
  numerical timezone                |                             |
YYYYMMDD_hhmmss (with local TZ)     | gdate +%F_T%H%M%S%z         | 2025-02-01_T15-30-00-0800  
  numerical timezone (no dash)      |                             |

Notes:  
* use this for filenames