Dateplus featured online in UnixReview.com, Shell Corner, March 2004.
http://www.OrlandoKuntao.com
 
Dateplus: Dates Incremented, Decremented, Repeated, Et al.
(C and AWK methods)
 
by Bob Orlando
 

Although anything but a mathematician, I've always been fascinated by date routines.  That fascination, coupled with the frenzied push at the end of the last century to make everything Y2K-compliant, prompted me to make a brief foray into "C" programming and develop some useful date routines.  My objective was not to develop libraries or functions that could be easily incorporated into other "C" programs--there are plenty of "C" date libraries out there already.  Rather, my objective was to develop a standalone, highly portable program that returned a variety of frequently requested and adjusted dates, suitable for Bourne shell scripts.

Bourne shell scripts were my target primarily because in our shop, batch production scripts were written in Bourne.  The policy was Korn for interactive use; Bourne for batch.  Besides, anything written in Bourne runs in Korn shell and practically any other shell as well.  Korn has many fine date tools and features ($SECONDS is one of which I am particularly fond for calculating process elapsed time), but those capabilities are not available in the Bourne shell.  Hence, dateplus.c was Bourne Smiley face(See  Holiday  Perl and Awk programs for easy ways to handle holidays as well as calculate nth business days.)

Date arithmetic in Unix is, at best, an inconsistent mess.  There are myriad methods in Awk, Perl, TCL, etc., for manipulating dates in Unix.  Over time, I've developed, collected, and codified "C" techniques into a single, portable utility called dateplus (about 600 lines of "C" code).  No special libraries are required for dateplus making it basically a compile and go, off the shelf tool that runs anywhere an ANSI "C" compiler is available.
 

Dateplus Usage and Options

Here are the supported options (together with non-trivial examples):
-b   Basedate of today (or date specified) since Jan. 1, 0001. 
Example:   dateplus -b 20030818  
Result: 731445
-h   Usage brief or help.
-H   Full documentation including history with a brief,
two-paragraph discussion of the Gregorian correction
to the Julian calendar made in 1582 and universally
adopted in 1752.
-J   Julian (yyyyJJJ) to Gregorian (yyyymmdd). 
Example:   dateplus -J 2003230
Result: 20030818
-j   Julian day (ddd) for today or yyyymmdd. 
Example:   dateplus -j 20030818
Result: 230
-s   Days 'since' (or until) yyyymmdd. 
Example:   dateplus -s 20000101   (run Aug. 19, 2003)
Result: 1326   (number of days since Y2K) 
Example:   dateplus -s 20040819   (run Aug. 19, 2003)
Result: -366    (number of days until Aug. 19, 2004)
-S   Unsigned days until (or since) yyyymmdd. 
Example:   dateplus -S 20040819   (run Aug. 19, 2003)
Result: 366    (number of days until Aug. 19, 2004)
-t   Tomorrow's date.
-u   Basedate of today (or date specified) since Jan. 1, 1970 (Unix epoch date). 
Example:   dateplus -u 20030819
Result: 12283  (suitable for 'lastchg' field in password shadow file)
-W   Date's weekday (long name). 
Example:   dateplus -W 17760704
Result: Thursday
-w   Date's weekday (abbreviated). 
Example:   dateplus -w 17760704
Result: Thu
-y   Yesterday's date.
[-+]days   Adjust by +|- nn days. 
Example:   dateplus -2   (Day before yesterday)
Example:   dateplus +2   (Day after tomorrow)
Example:   dateplus -1 20030101
Result: 20021231
Example:   dateplus -60 20030801
Result: 20030602
 
To adjust days with iterations (i.e. paydays).
 
Example:   dateplus +14 20021231 26
Result: 20030114
20030211
20030225
20030311
20030325
.  .  .
.  .
.

20031202
20031216
20031230
 
You can use the same method  (i.e.  dateplus +7 yyyymmdd nn)
to list, for example, nn Mondays beginning with yyyymmdd.
 
To return 10 days' dates (days 70-60 days) before Aug. 1.
       
Example:   dateplus -1 `dateplus -60 20030801` 10
Result: 20030601
20030531
20030530
20030529
20030528
20030527
20030526
20030525
20030524
20030523
 
For all options except weekday (-w), success is in indicated with a zero exit atatus.  Nonzero indicates failure.  With the weekday option, success returns an exit status of 0-6 (zero-based weekdays with Sunday being zero).  Any other status indicates failure.

The strength of dateplus is that most of the options support any properly formatted date--not just today.  I use dateplus for all of my date arithmetic needs in shell programming.  I've run dateplus on Solaris 5-9, Red Hat Linux 8, SCO Open Server V, and Windows 9x through XP.

Dateplus comes with its own built-in usage brief (-h) and complete online documentation (-H).  The documentation display is some 120 lines long so you may want to page it (pipe it through "more").

For all practical purposes, any date the user wishes to use as a yyyymmdd (from 01-01-0001 through 12-31-9999) is accepted.  The resultant date is returned via stdout in yyyymmdd form.  The program is especially useful for calculating yesterday's, tomorrow's, or any other desired date.  Additionally, by specifying an iteration value (the last argument) the program generates that number of dates, each adjusted on the previous date (handy for calculating paydays and the like).  Because the program writes to stdout, its output is easily redirected to a file where the results can be subsequently edited or munged as needed.  The program also comes with help options (-h and -H for summary and detailed outputs, respectively).
 

History

The Gregorian correction to the Julian calendar made in October, 1582 dropped 10 days.  That is, October 4, 1582 was followed immediately by October 15.  This papal correction, although scientifically correct, was not adopted by non-Catholic countries until almost two centuries later in 1752.  In September, 1752 the English calendar was adjusted to Pope Gregory's method of correction and 11 days were dropped (September 14, followed September 2).

While this routine easily calculates the date that far back, it does not drop October 5-14, 1582 or September 3-13, 1752.  If this routine is used to calculate dates that far back, the previously adjusted and dropped dates will appear as if no calendar corrections were ever made.  Neither does dateplus address the calendar adjustment that will likely happen around the year 4000 A.D.  Those technical purists who will be around then can handle that Smiley face.  Since most real world applications don't come anywhere near those extremes, dateplus' accuracy is sufficient for most.
 

Testing

To test the numerous dateplus options, simply run the following commands (or put them into a script):
              
      Command line               Returns
      ------------------------   ---------------------
      dateplus -t                Tomorrow's yyyymmdd
      dateplus +2                Day after tomorrow
      dateplus -y                Yesterday's yyyymmdd
      dateplus -2                Day before yesterday
      dateplus +14 20021231 26   Biweekly paydays for 2003
      dateplus -b                Today's base date
                                  (days since Jan. 1, 0001)
      dateplus -b 20000101       Basedate for Jan. 1, 2000
                                  (days since Jan. 1, 0001)
      dateplus -u                Today's Unix epoch base date
                                  (days since Jan. 1, 1970)
      dateplus -u 20000101       Basedate for Jan. 1, 2000
                                  (days since Jan. 1, 1970)
      dateplus -s 19441026       Days since Oct. 26, 1944
      dateplus -s 20141026       Days until Oct. 26, 2014 (signed result)
      dateplus -S 20141026       Days until Oct. 26, 2014 (unsigned result)
      dateplus -W 19991231       Day of week (long name),   Dec. 31, 1999
      dateplus -w 19991231       Day of week (abbreviated), Dec. 31, 1999
      dateplus -j 19441026       300 (ddd) for Oct. 26, 1944
      dateplus -J 1944300        yyyymmdd for 1944300 Julian
      dateplus -h                Usage brief (help)
      dateplus -H | more         Full Documentation (HELP)
              
            
Doubtless, there are more efficient, date routines out there.  But portability and ease of use were my only goals, and dateplus meets them.  Dateplus is as portable as ANSI "C", which means it produces the same results in practically any operating system: Unix, Windows, you name it.  It's also easy to use.  Standard libraries are all you need--just compile and go.
 

AWK Version

Having worked in shops where access to "C" was frowned upon, I developed an AWK version of this same program, dateplus.awk.  It offers all but the little-used Julian to Gregorian date conversion (-J) option, and iterations argument functionality (iterations are easily handled using a simple shell loop).  For example, the following shell code prints the next 26 paydays following December 31, 2003.
              
      payday="20031231"
      paydays=""
      for n in . . . . . . . . . . . . . . . . . . . . . . . . . 26
      do
         payday="`dateplus.awk -- +14 $payday`"
         paydays="$paydays\n$payday"
      done
      echo "Pay Days: $paydays"
              
            
The "C" program is roughly 3 times faster than the Awk script, but the results are the same.  Also, if your OS recognizes the '#!' (she-bang) syntax, you can place a  '#!/usr/bin/nawk -f'  (or gawk) at the start of this program thereby skipping the  'nawk -f'  during invocation.  It doesn't speed it up any, but running
'dateplus.awk -- +14'
just looks cleaner than
'nawk -f dateplus.awk -- +14'. 

Conclusion

The actual code in dateplus is not new; neither are the techniques.  However, the functionality, encapsulated in a single, highly portable, self-documented program is.  That's the value of dateplus.  Other articles have told us how to use date mathematics.  Dateplus does it.
 

Footnote

Please, feel free to send comments/suggestions to Bob@OrlandoKuntao.com.  That said, acceptance is based on readable, easy to follow code.  Highly efficient, but difficult to follow code [read obfuscated] is unacceptable since readable code (even if  less efficient) eases the maintenance chore.
Artificial  intelligence  is  no  match  for  natural  stupidity.
 
©Copyright Bob Orlando, 1995-2016
All rights reserved.
http://www.OrlandoKuntao.com
E-mail: Bob@OrlandoKuntao.com
Last update:  Feb. 2, 2016
by Bob Orlando
Web Site of Bob Orlando: Instructor in Kuntao-Silat (Chinese kuntao and Dutch-Indonesian pukulan pentjak silat), author of two popular martial art books: "Indonesian Fighting Fundamentals" and "Martial Arts America: A Western Approach to Eastern Arts"; and producer of four martial art videos: Fighting Arts of Indonesia, Reflex Action, Fighting Footwork of Kuntao and Silat, Fighting Forms of Kuntao-Silat. Offering practical martial arts instruction to adults living in and throughout the Denver metropolitan area including, Lakewood, Littleton, Morrison, and Golden Colorado.