First thing to accept into your heart - ISO 8601 (wikipedia).

For the last word on time formats strings, see man strftime which I believe is their canonical source.

Part I - What time would you like the date program to return

--date and -d option are the same. They allow you to specify a specific moment in time if you are not happy with the default behavior of "right now!". You can either specify a different absolute time in history or the future, a relative shift in time, or both. This option must be immediately followed by a special string that contains certain elements. I believe that the structure of the string must be something like this:

`[time] [[days  month][ year]|[month days][ , year]] [modifier unit[ ago]]`

The order of the three elements time, date, and modifier are not relevant. The default date/time can be explicitly stated. It is now. There is also some functionality with keywords tomorrow, next, and yesterday, although I found yesterday to be unpredictable.

  • time = 15:0 and 3pm and 15:00 and 15:00:00 and 15:0:0 are all valid for 15:00. The hours must be less than 13 for am/pm to work. Colons are the big clue that it’s dealing with a time.

  • days = days is the number of days since the last day of the preceding month. The range is 0 to some big number. If you say "0 mar 1948" for example, you get Feb 29, 1948. Likewise, "40 mar 1948" gives April 09, 1948.

  • month = can be the full name of the month or the first 3 letter and is completely non-case sensitive.

  • year = can be last 2 digits if between 1969 and 2037 (00-37 and 69-99) or it can be a full 4 digits between 1902-2037.

  • modifier = is a number that represents a number of time unit to move from the original moment.

  • unit = is the time units to displace the specified moment by. Examples that work are hours, minutes, seconds, days, weeks, months, years.

  • ago = this is the word ago and it reverses the direction sense of the modifier so that it counts backward in time.

Part II - How would you like the date program to return that time

Once you have decided on the date you would like the date command to output by using the -d or --date argument (or not), you can then modify its format. This is done by starting a string with a +. You don’t need to quote the string if it doesn’t contain spaces or otherwise need quoting (but it seldom hurts to quote things like this). This string is basically output verbatim by the date command with substitutions occuring for % symbols followed by some code. The codes:

Time fields
  • %H = hour (00..23);

  • %I = hour (01..12);

  • %k = hour ( 0..23);

  • %l = hour ( 1..12);

  • %M = minute (00..59);

  • %p = locale’s AM or PM;

  • %r = time, 12-hour (hh:mm:ss [AP]M);

  • %s = seconds since 1970-01-01 00:00:00 UTC (a nonstandard extension);

  • %S = second (00..61); %T=time, 24-hour (hh:mm:ss);

  • %X = locale’s time representation (%H:%M:%S);

  • %Z = time zone (e.g., EDT), or nothing if no time zone is determinable

Date fields
  • %a = locale’s abbreviated weekday name (Sun..Sat);

  • %A = locale’s full weekday name, variable length (Sunday..Saturday);

  • %b = locale’s abbreviated month name (Jan..Dec);

  • %B = locale’s full month name, variable length (January..December);

  • %c = locale’s date and time (Sat Nov 04 12:02:33 EST 1989);

  • %d = day of month (01..31);

  • %D = date (mm/dd/yy);

  • %h = same as %b;

  • %j = day of year (001..366);

  • %m = month (01..12);

  • %U = week number of year with Sunday as first day of week (00..53);

  • %w = day of week (0..6) with 0 corresponding to Sunday;

  • %W = week number of year with Monday as first day of week (00..53);

  • %x = locale’s date representation (mm/dd/yy);

  • %y = last two digits of year (00..99); %Y=year (1970…)

Offset Wrong Date Of Files Due To Bad Clock Setting

You have a bunch of files that all have the wrong date because the computer they were created on had the wrong time setting. How can you adjust them to be correct as if they had been created with the correct timestamps? This means that all the relative dates between files should be preserved. This happens a lot with cameras where the time is set badly.

This fixes files taken with a camera whose clock was 14 minutes fast.

for P in *jpg; do touch -r ${P} -d '-14 min' ${P} ; done

This one was from a GOPRO that was off by quite a bit more. But I was able to figure out the exact offset to bring all the photo timestamps to the correct time.

for P in *JPG; do touch -r ${P} -d '+3 year 10 month 18 day 2 hour' ${P} ; done

The documentation for the touch command with relative offsets sucks info pages.

You might think about doing this too for camera problems.

jhead -dsft *.jpg

That will set the EXIF information in the photos to be consistent with the timestamps.

Complete Examples

Date Examples
[~]$ date -d "January 18 , 1969 30 seconds 3 minutes ago" +cxe%y%m%d-@-%H%M%S
cxe690117-@-235630

[~]$ date '+The current time is: %H:%M:%S on %Y.%m.%d'
The current time is: 22:55:56 on 1999.02.10

[~]$ date -d '17 Jan 1969' +%A
Friday
Acceptable Format For An RSS pubDate Tag
DATE=$(date -d "${DATE}" '+%a, %d %b %Y %H:%M %Z')
Quarters

I believe some newer date commands have a +q but as late as CentOS 7, they don’t. Let’s say a public database is published every quarter 7 months after the events it describes. What quarter can you expect to find available today?

$ echo $(date -d"-7 months" +%Y)q$(((10#$(date -d"-7 months" +%m)-1)/3+1))
2017q3
UTC

People send you messages from "services" beyond their control and they’re dated with UTC. You’d like to know what time UTC is right now because you’re not 100% sure how DST is playing (and you never should be confident). I use this alias.

alias utc='TZ=UTC0 date "+%Y-%m-%d %H:%M:%S"'
Calendar

I often like to use Vim’s :r! cal... to include calendars in my email. But at the end of the month, I want the beginning of the next month too. Unfortunately cal -3 shows a bunch of weeks I don’t care about (because they’re history). Here is a good technique.

$ for N in {0..2}; do cal $(date -d "+$N month" "+%m %Y"); done
    August 2018
Su Mo Tu We Th Fr Sa
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

   September 2018
Su Mo Tu We Th Fr Sa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
    October 2018
Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6
 7  8  9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

Also keep in mind ncal which can be easier to manually fix.

$ ncal -3
    July 2018         August 2018       September 2018
Su  1  8 15 22 29        5 12 19 26        2  9 16 23 30
Mo  2  9 16 23 30        6 13 20 27        3 10 17 24
Tu  3 10 17 24 31        7 14 21 28        4 11 18 25
We  4 11 18 25        1  8 15 22 29        5 12 19 26
Th  5 12 19 26        2  9 16 23 30        6 13 20 27
Fr  6 13 20 27        3 10 17 24 31        7 14 21 28
Sa  7 14 21 28        4 11 18 25        1  8 15 22 29

To Change System Time

date -s 16:08:45

I don’t know if this changes the CMOS setting, but it changes what time Linux thinks it is.

There is a howto in /usr/doc/HOWTO/mini/Clock that describes how to have a an adjustment mechanism keep your clock up to date very accurately.

Here’s a full specification that should get the date as well… date 110123361999.50

The format is actually MMDDhhmmYYYY.ss An odd format, but that’s what it is…

Cryptographic Temporal Attestation

Interested in cryptographic temporal attestation on blockchains. I am. Here is a very good article about it. Here are some very interesting and sensible looking services.