15

How can you calculate the number of days since 1/1/1970? This is for updating the shadowLastChange attribute on OpenLDAP.

Is there a way to do this using the linux date command?

Dave Drager
  • 8,315
  • 28
  • 45
nitins
  • 2,527
  • 15
  • 42
  • 65
  • In Bash and most modern Bourne-derived shells, `$()` is preferred over backticks for [readability and other reasons](http://mywiki.wooledge.org/BashFAQ/082). `echo $(( $(date ...) / 86400 ))` – Dennis Williamson Jan 10 '11 at 14:03
  • Don't have 2000 yet... can someone edit and fix the title :-) – Déjà vu Jan 10 '11 at 14:32

4 Answers4

25

ring0 beat me by a few seconds, but the full command is:

echo $(($(date --utc --date "$1" +%s)/86400))

This goes by UTC time. Result:

root@hostname:~# echo $((`date --utc --date "$1" +%s`/86400))
14984

A quick check with WolframAlpha shows that this is the correct value.

Dave Drager
  • 8,315
  • 28
  • 45
  • 1
    what about leap seconds? :) – netvope Feb 21 '15 at 23:43
  • 1
    @netvope After an additional leap second, unix time is reset by one again. So each day adds exactly 86400 unix seconds. However, unix time 915148800 may stand for both UTC 1998-12-31T23:59:60 and 1999-01-01T00:00:00 https://en.wikipedia.org/wiki/Unix_time#Leap_seconds – Debilski Feb 01 '16 at 12:14
12

I think this is the simplest method:

expr $(date +%s) / 86400
GregL
  • 9,030
  • 2
  • 24
  • 35
DarkHorse
  • 121
  • 1
  • 2
10

The date command can give you the number of seconds since 1970-01-01 00:00:00 UTC.

  date +"%s"

You can divide the result by 3600*24 to get the number of days (UTC).

E.g. in Bash

  x=`date +"%s"` ; echo $(( $x / 3600 / 24 ))

to display the number of days.

Déjà vu
  • 5,408
  • 9
  • 32
  • 52
2

I needed to solve this as well, but I wanted to get the same value for the day# regardless of time of day. With approaches like those shown here, the value will change at midnight UTC instead of midnight local time. This probably seems like less of an issue in the EU or the U.S. East Coast, which are close enough to UTC that the day value won't change in the middle of the typical work day, but in, e.g., California, the day change would occur at 4pm PST, which might be inconvenient. I imagine Australians would be especially annoyed to have the day value change in late morning.

If we want to correct for that, we need to add the offset from UTC before dividing by secs/day. Fortunately, the Linux date command includes a %z format sequence which reports the offset from UTC. While the standard format (this result is for Denver time, MDT):

$ date +%z
-0600

. . . isn't directly usable in a calculation, the right modifiers will yield what we want:

$ date +%-:::z
-6

Put that together with the usual secs/hours/days conversions, and I believe the following should output the days since 1/1/1970, with 1/1/1970 itself being day zero, and the value incrementing at midnight local time:

echo $(( ( $(date +"%s + ( %-:::z * 3600)") ) / 86400 ))

This simple calculation will not work for time zones that are not offset from UTC by whole hours (e.g., India, TZ=Asia/Kolkata), since the "+5:30" produced by date +%-:::z will produce an "invalid character in expression" error when used in the above statement.

oracleif
  • 21
  • 3