7

On the Unix Bash commandline, I want to calculate the date from 1125 days ago using the base operating system (e.g. No Perl or Python).

On systems running GNU Date, I can do something like this:

ubuntu $ date --date="1125 days ago"
Wed Nov  7 15:12:33 PST 2007

FreeBSD or MacOSX systems don't ship with GNU Date, and don't support values like "X days ago".

freebsd81 $ date --date="+1125 days ago"
date: illegal option -- -

I can calculate a date from a few days ago on a Mac or FreeBSD system, but this is limited to a few days:

# Today is really Dec 6, 2010. 4 days ago it was:
macosx $ TZ=GMT+96 date +%Y%m%d
20101202

# But that doesn't work if I want to see the date 8 days ago:
macosx $ TZ=GMT+192 date +%Y%m%d
20101206

Can I calculate old dates on non-GNU systems without delving into tools like Perl or Python? Or must I use a more powerful scripting language?

3 Answers 3

7

Well, you can do something sneaky like:

$ echo "`date +%s` - (1125 * 24 * 60 *60)" |bc
1194478815
$ date -r 1194478689
Wed, 07 Nov 2007 18:38:09 -0500

Tested on OpenBSD (definitely non gnu based date), and seems to work.

Breaking it down in steps:

  • get the current unixtime (seconds since beginning of unix epoch):
  $ date +%s
  1291679934
  
  • get the number of seconds in 1125 days
  $ echo "1125 * 24 * 60 *60" | bc
  97200000
  
  • subtract one from the other (1291679934 - 97200000) = 1194478815

  • use the new unixtime (1194478815) to print a pretty date

    $ date -r 1194478689
    Wed, 07 Nov 2007 18:38:09 -0500
    
  • As an alternative, on solaris you can do this to print the date*:

    /bin/echo "0t1194478815>Y\n<Y=Y" |adb

* referenced from http://www.sun.com/bigadmin/shellme/

Also, an alternative on Solaris for getting the current timestamp from the date command** is:

/usr/bin/truss /usr/bin/date 2>&1 |  nawk -F= '/^time()/ {gsub(/ /,"",$2);print $2}'

** referenced from http://www.commandlinefu.com/commands/view/7647/unix-timestamp-solaris

6
  • Note that %s and date -r are BSDisms (from the very early days, so they're on all BSD platforms). Don't expect to see them on System V platforms (e.g. Solaris has neither). Commented Dec 7, 2010 at 0:09
  • Ah, Solaris, how I love thee... (;
    – gabe.
    Commented Dec 7, 2010 at 0:14
  • @Gilles: Are you sure? Solaris has a multitude of bin directories, such as /usr/ucb/bin, that contain versions from other variations of unix. SunOS 4.X was BSD-based after all.
    – camh
    Commented Dec 7, 2010 at 1:24
  • This fails when any of the intervening days have more or less than 60*60*24 seconds, such as leap seconds and calendar changes.
    – Sparr
    Commented Dec 7, 2010 at 7:01
  • 1
    @Sparr: Good point. A safe approach is to subtract the current time of day from the current absolute date, and add 12*60*60. This returns a time-of-day between 10:59 and 13:01. Adding 24-hour periods to this and obtaining the corresponding date is safe. Commented Dec 7, 2010 at 19:06
3

Previous answer was far too complicated. FreeBSD/macOS have the -v flag for date, from the MAN page (abbreviated description):

Adjust (i.e., take the current date and display the result of the adjustment; not actually set the date) the second, minute, hour, month day, week day, month or year according to val. If val is preceded with a plus or minus sign, the date is adjusted forwards or backwards according to the remaining string, otherwise the relevant part of the date is set. The date can be adjusted as many times as required using these flags. Flags are processed in the order given.

So for your purpose, date -v1125d will simply do what you need

$ date; date -v-1125d
Thu 19 Oct 2017 11:35:25 EDT
Sat 20 Sep 2014 11:35:25 EDT
0

I was having a similar issue i found the dateutils pkg for OpenBSD 6.4. It was a simple pkg_add dateutils for me.

#!/bin/ksh
# Using dateutils dadd (get current date) -1month -f (format to strftime)
# Set Year in YYYY formant y is YY format
lastMonth=$(dadd date -1mo -f "%Y.%m")
echo $lastMonth
mkdir /home/$usr/History/$lastMonth

My out put here is

#2018.11

UPDATE 1

I am running this command on 2018.12.10

HostNameHere# dadd date -1125d -f "%Y.%m"

Result

 2015.11

It supports any time additions or subtractions that i can tell. Here is the commands help print out. #dadd -h (this is not the entirety of the print out. There is more info on options.

    Usage: dadd [OPTION]... [DATE/TIME] [DURATION]
    Add DURATION to DATE/TIME and print the result.
If DATE/TIME is omitted but DURATION is given, read a list of DATE/TIMEs from
stdin. If DURATION is omitted but DATE/TIME is given, read a list of DURATIONs from
stdin.

Durations are specified as nY, nMO, nW, or nD for years, months, weeks, or days
respectively, or nH, nM, nS for hours, minutes, and seconds, where N is a
(possibly negative) number.  The unit symbols can be written lower-case as well
(y, mo, w, d, h, m, s) and the unit symbol `d' can be omitted.

Note that duration addition is not commutative!
  2000-03-30 +1mo +1d -> 2000-05-01
  2000-03-30 +1d +1mo -> 2000-04-30

Here are the commands.

Here are the formatting options.

2
  • (1) It's nice that this program supports -1mo. Can you demonstrate that it allows the user to calculate the date from 1125 days ago, as the question asks? (2) The question says "using the base operating system (e.g. No Perl or Python)." That would seem to preclude adding a new package. Commented Dec 7, 2018 at 20:41
  • 1
    @G-Man Thank you for the comment. I am new to contributing on StackExchange. Thank you for the help. See UPDATE 1 Commented Dec 10, 2018 at 14:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .