A dateplus C program is also available.
#!/usr/bin/nawk -f
# SccsId[] = "@(#)dateplus.awk 2.8 03/19/10"
#----------------------------------------------------------------------#
# dateplus.awk #
# -------------------------------------------------------------------- #
# #
# Copyright (c) 1995-2010 by Bob Orlando. All rights reserved. #
# #
# Permission to use, copy, modify and distribute this software #
# and its documentation for any purpose and without fee is hereby #
# granted, provided that the above copyright notice appear in all #
# copies, and that both the copyright notice and this permission #
# notice appear in supporting documentation, and that the name of #
# Bob Orlando not be used in advertising or publicity pertaining #
# to distribution of the software without specific, written prior #
# permission. Bob Orlando makes no representations about the #
# suitability of this software for any purpose. It is provided #
# "as is" without express or implied warranty. #
# #
# BOB ORLANDO DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS #
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY #
# AND FITNESS. IN NO EVENT SHALL BOB ORLANDO BE LIABLE FOR ANY #
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES #
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER #
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, #
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF #
# THIS SOFTWARE. #
# #
#----------------------------------------------------------------------#
#----------------------------------------------------------------------#
# This program is the Awk equivalent of my C program, dateplus.c. #
# However, this program still supported/maintained as part of my #
# shell library for those sites which restrict C-compiler access. #
# -------------------------------------------------------------------- #
# Program documentation and notes located at the bottom of script. #
#----------------------------------------------------------------------#
BEGIN \
{
progname = "dateplus.awk"
#------------------------------------------------------------#
# If user supplies no args (ARGC == 1), then show usage and #
# exit. Else, continue and see if they gave us options. #
#------------------------------------------------------------#
if (ARGC == 1) # Zero-based numbering drives me nuts!
exit_usage()
#------------------------------------------------------------#
# Set up the following arrays. #
#------------------------------------------------------------#
split("0 31 59 90 120 151 181 212 243 273 304 334 365", julian_days)
split("0 31 60 91 121 152 182 213 244 274 305 335 366", julian_leap)
adj = 0
opt_v = 0
#------------------------------------------------------------#
# If last arg looks like a valid date, parse, validate, and #
# use it, else, use the current yyyymmdd. #
#------------------------------------------------------------#
if (ARGV[ARGC-1] ~ /^[0-2][0-9][0-9][0-9][0-1][0-9][0-3][0-9]$/)
{
yyyy = substr(ARGV[ARGC-1],1,4)
mm = substr(ARGV[ARGC-1],5,2)
dd = substr(ARGV[ARGC-1],7,2)
validate_yyyymmdd(yyyy,mm,dd)
}
else
{
#-------------------------------------------------------#
# Calling date with "+\%Y\%m\%d" (with escaped percent #
# signs) avoids hassles with SCCS and percentYpercent. #
#-------------------------------------------------------#
"date +\%Y\%m\%d" | getline yyyymmdd
yyyy = substr(yyyymmdd,1,4)
mm = substr(yyyymmdd,5,2)
dd = substr(yyyymmdd,7,2)
}
#------------------------------------------------------------#
# Verbose (development) output wanted? #
#------------------------------------------------------------#
for (n=1; n<ARGC; n++)
{
if (ARGV[n] == "-v") # Verbose option
{
opt_v = 1
ARGV[n] = ""
shift_ARGV()
break
}
}
if (opt_v) print "Using "yyyy""mm""dd
#------------------------------------------------------------#
# Validate and process remaining options. #
#------------------------------------------------------------#
if (ARGV[1] == "-y") # -y = Yesterday's date
calculate_date(yyyy,mm,dd,-1)
else if (ARGV[1] == "-t") # -t = Tomorrow's date
calculate_date(yyyy,mm,dd,1)
else if (ARGV[1] == "-b") # -b = Basedate for today|yyyymmdd
basedate(yyyy,mm,dd,1)
else if (ARGV[1] ~ /^-[Ww]$/) # -[Ww] = Weekday for today|yyyymmdd
calc_weekday(yyyy,mm,dd)
else if (ARGV[1] == "-S") # -S = Days since yyyymmdd (unsigned)
days_since(yyyy,mm,dd,"S")
else if (ARGV[1] == "-s") # -s = Days since yyyymmdd
days_since(yyyy,mm,dd)
else if (ARGV[1] == "-u") # -u = Days since Unix epoch date
days_since(yyyy,mm,dd,"u")
else if (ARGV[1] == "-j") # -j = Julian date
julian_date(yyyy,mm,dd)
else if (ARGV[1] == "-H") # -H = Full documentation
show_documentation(progname)
else if (ARGV[1] == "-h") # -h = Summary help (Usage)
exit_usage()
else if (ARGV[1] ~ /^-[0-9]+$/) # Negative adjustment value
adj = ARGV[1]
else if (ARGV[1] ~ /^-/ && ARGV[1] !~ /^-[0-9]+$/) # Oops
exit_usage("Invalid "progname" option, '"ARGV[1]"'.")
#------------------------------------------------------------#
# Options (and negative adj days) look good; skip past'em. #
#------------------------------------------------------------#
if (ARGV[1] ~ /^-[bhstuwy]$/ || ARGV[1] ~ /^-[0-9]+$/)
shift_ARGV()
#------------------------------------------------------------#
# Positive (or unsigned) integer for adj days next? #
#------------------------------------------------------------#
if (ARGV[1] ~ /^\+?[0-9]+$/ && adj == 0)
{
adj = ARGV[1]
shift_ARGV()
}
#------------------------------------------------------------#
# OK, do it the long way--see if I care :-)) #
#------------------------------------------------------------#
if (opt_v)
print "calculate_date("yyyy","mm","dd","adj")"
calculate_date( yyyy , mm , dd , adj )
exit 0
} # E.O.BEGIN
#======================================================================#
# U S E R F U N C T I O N S #
# (in alphabetical order) #
#----------------------------------------------------------------------#
function basedate( \
YYYY,MM,DD,OPT_B, \
yyyy,cc,ddddd,leapdays,cc_leapdays,accum_days \
) #
# -------------------------------------------------------------------- #
# Globals: julian_days[] and julian_leap[] #
# Calls: leap_year() #
#----------------------------------------------------------------------#
{
if (opt_v)
{
print "basedate(YYYY,MM,DD,OPT_B)"
print "basedate("YYYY","MM","DD","OPT_B")"
}
#--------------------------------------------------------#
# First, decrement the year and get the number of days #
# for all the years preceeding it (Anno Domini). #
#--------------------------------------------------------#
yyyy = YYYY
if ((yyyy - 1) > 0)
{ ;if (opt_v) print " YYYY =|"YYYY "|"
yyyy-- ;if (opt_v) print " yyyy =|"yyyy "|"
cc = int(yyyy / 100) ;if (opt_v) print " cc =|"cc "|"
ddddd = yyyy * 365 ;if (opt_v) print " ddddd =|"ddddd "|"
leapdays = int(yyyy / 4) ;if (opt_v) print " leapdays =|"leapdays "|"
cc_leapdays = (cc > 0) ? (int(cc / 4)) : 0 ;if (opt_v) print " cc_leapdays=|"cc_leapdays"|"
ddddd = ddddd + leapdays - cc + cc_leapdays ;if (opt_v) print " ddddd =|"ddddd "|"
yyyy++ ;if (opt_v) print " yyyy =|"yyyy "|"
}
ddddd += DD ;if (opt_v) print " ddddd =|"ddddd "|"
#---------------------------------------------------------#
# Add the previous month YTD days to our ddddd. If it #
# is a leap year, assign julian_leap[] to accum_days[]. #
# Then add in YTD days for previous months of this year #
#---------------------------------------------------------#
if (leap_year(yyyy))
for (i=0; i<13; i++) accum_days[i] = julian_leap[i]
else
for (i=0; i<13; i++) accum_days[i] = julian_days[i]
ddddd += accum_days[MM += 0] # 'MM += 0' removes leading zero
if (OPT_B) # If all they want is basedate, print it and exit.
{
print ddddd
exit 0
}
if (opt_v)
print "==> return ("ddddd")"
return ( ddddd )
} # function basedate
#----------------------------------------------------------------------#
function calc_weekday(YYYY,MM,DD, ddddd,weekdays,i) #
#----------------------------------------------------------------------#
{
if (opt_v)
{
print "calculate_weekday(YYYY,MM,DD)"
print "calculate_weekday("YYYY","MM","DD")"
}
if (ARGV[1] == "-w") # -[Ww] = Weekday for today|yyyymmdd
split("Sun Mon Tue Wed Thu Fri Sat", weekdays)
else
split("Sunday Monday Tuesday Wednesday Thursday Friday Saturday", weekdays)
ddddd = (basedate(YYYY,MM,DD) % 7)
print weekdays[ddddd+1]
exit ddddd # ddddd = day number [0-6]
#------------------------------------------------------------------#
# http://www.tondering.dk/claus/cal/calendar26.txt #
# In day of the week calculations, the divisions are integer #
# divisions, in which remainders are discarded. #
# a = (14 - month) / 12 #
# y = year - a #
# m = month + 12*a - 2 #
# Julian d = (5 + day + y + y/4 + (31*m)/12) mod 7 #
# Gregorian d = (day + y + y/4 - y/100 + y/400 + (31*m)/12) mod 7 #
#------------------------------------------------------------------#
} # function calc_weekday
#----------------------------------------------------------------------#
function calculate_date(YYYY,MM,DD,ADJ, i,month_days) #
# -------------------------------------------------------------------- #
# Calls: leap_year(), ddddd_to_yyyymmdd(), and basedate() #
#----------------------------------------------------------------------#
{
if (opt_v)
{
print "calculate_date(YYYY,MM,DD,ADJ)"
print "calculate_date("YYYY","MM","DD","ADJ")"
}
split("31 28 31 30 31 30 31 31 30 31 30 31", month_days)
if (leap_year(YYYY) && mm == 2) month_days[2] = 29
if (ADJ < 0 && ADJ > (DD * -1)) # Shortcut -n
{
if (opt_v)
print "printf(\"%4d%02d%02d\n\","YYYY","MM",("DD" + "ADJ"))"
printf( "%4d%02d%02d\n" , YYYY , MM ,( DD + ADJ ))
}
else if (ADJ > 0 && ((DD + ADJ) <= month_days[MM+0])) # Shortcut +n
{
if (opt_v)
print "printf(\"%4d%02d%02d\n\","YYYY","MM",("DD" + "ADJ"))"
printf( "%4d%02d%02d\n" , YYYY , MM ,( DD + ADJ ))
}
else # Long way
{
if (opt_v)
print "ddddd_to_yyyymmdd(basedate("YYYY","MM","DD") + "ADJ")"
print ddddd_to_yyyymmdd(basedate( YYYY , MM , DD ) + ADJ )
}
exit 0
} # function calculate_date
#----------------------------------------------------------------------#
function days_since( \
YYYY,MM,DD,OPT, \
yyyymmdd,mm,dd,yyyy,ddddd,ddddd_yyyy \
) # Global variables: progname #
#----------------------------------------------------------------------#
{
ddddd = basedate(YYYY,MM,DD)
if (OPT != "u")
{
ddddd_yyyy = ddddd
"date +\%Y\%m\%d" | getline yyyymmdd # Today's date
yyyy = substr(yyyymmdd,1,4)
mm = substr(yyyymmdd,5,2)
dd = substr(yyyymmdd,7,2)
ddddd = basedate(yyyy,mm,dd)
ddddd -= ddddd_yyyy
if (OPT == "S" && ddddd < 0) ddddd = ddddd - ddddd - ddddd
}
else
{
if (YYYY >= 1970)
{
ddddd_yyyy = basedate(1970,01,01)
ddddd -= ddddd_yyyy
}
else
{
printf("This is a trick question, right? ") |"cat 1>&2"
printf("You requested the number of days since\n") |"cat 1>&2"
printf("Jan. 1, 1970, (-u option) but you provided ")|"cat 1>&2"
printf("a date that is older than that.\n") |"cat 1>&2"
printf("%s terminated.\n", progname) |"cat 1>&2"
exit 6
}
}
print ddddd
exit 0
} # function days_since
#----------------------------------------------------------------------#
function ddddd_to_yyyymmdd(DDDDD, ddddd,yyyy,mmdd,i) #
# -------------------------------------------------------------------- #
# Globals: julian_days[] and julian_leap[] #
#----------------------------------------------------------------------#
{
if (opt_v)
{
print "ddddd_to_yyyymmdd(DDDDD)"
print "ddddd_to_yyyymmdd("DDDDD")"
}
yyyy = ddddd = reduce(DDDDD)
if (opt_v) print "yyyy = ddddd = "ddddd
sub(/-.*$/,"", yyyy); yyyy += 0 # "+= 0" ensures numeric context
sub(/^.*-/,"",ddddd); ddddd += 0
if (opt_v)
{
print "yyyy = |"yyyy"|"
print "ddddd = |"ddddd"|"
}
if (leap_year(yyyy))
for (i in julian_leap)
julian[i] = julian_leap[i]
else
for (i in julian_days)
julian[i] = julian_days[i]
#------------------------------------------------------------#
# Reduce ddddd to month and day (we already have the year). #
#------------------------------------------------------------#
for (i=13; i>0; i--)
{
if (opt_v)
{
print "if (julian["i"] < "ddddd")"
print "if ("julian[i]" < "ddddd")"
}
if (julian[i] < ddddd)
{
# if (leap_year(yyyy) && i > 2) ddddd++ # 20080406.164435
ddddd -= julian[i]
mmdd = sprintf("%02d%02d", i, ddddd)
break
}
}
if (opt_v)
{
print "return (yyyy\"\"mmdd)"
print "return ("yyyy""mmdd")"
}
return ( yyyy""mmdd )
} # function ddddd_to_yyyymmdd
#----------------------------------------------------------------------#
function exit_usage(ERRMSG) # Global vars: progname #
#----------------------------------------------------------------------#
{
if (ERRMSG != "") print "\n"ERRMSG | "cat 1>&2"
print "\nUsage: [gn]awk -f "progname" -- -bHhjSstuvWwy -|+adj yyyymmdd.\n",
"\n -- = Allows AWK to pass script options and args." ,
"\n -b = Basedate for today or yyyymmdd." ,
"\n -H = Full formal documentation (functions only" ,
"\n when the current working directory is the" ,
"\n program directory)." ,
"\n -h = Summary help (Usage)." ,
"\n -j = Julian day for today or yyyymmdd." ,
"\n -S = Days since (or until) yyyymmdd (unsigned both).",
"\n -s = Days since (or until) yyyymmdd (signed future).",
"\n -t = Tomorrow's date." ,
"\n -u = Basedate of today|yyyymmdd since" ,
"\n Jan. 1, 1970--the Unix epoch date" ,
"\n (essentially 'dateplus -s 19700101')." ,
"\n -v = Verbose output (primarily for development)." ,
"\n -W = Date's long weekday" ,
"\n -w = Date's abbreviated weekday" ,
"\n -y = Yesterday's date.\n" ,
"\n adj = Adjustment days that may be positive or" ,
"\n negative (prefix sign annotation only)." ,
"\n By itself (with no yyyymmdd date following," ,
"\n yields an adjusted date that is calculated" ,
"\n from today's date.\n" ,
"\n yyyymmdd = Optional date from which the adjusted date" ,
"\n is calculated.\n" ,
"\n "progname" terminated.\n"
exit 7
} # function exit_usage
#----------------------------------------------------------------------#
function julian_date(YYYY,MM,DD, ddd) # Global vars: progname #
#----------------------------------------------------------------------#
{
ddd = reduce(basedate(YYYY,MM,DD))
sub(/^.*-/,"",ddd)
printf("%03d\n", ddd)
exit 0
} # function julian_date
#----------------------------------------------------------------------#
function leap_year(YYYY) # YYYY = year. Returns true|false (1|0). #
#----------------------------------------------------------------------#
{
return (((YYYY%4 == 0 && YYYY%100 != 0) || (YYYY%400 == 0)) ? 1 : 0)
} # function leap_year
#----------------------------------------------------------------------#
function reduce(DDDDD, yyyy,ddddd,cc,leapdays,cc_leapdays,i) #
#----------------------------------------------------------------------#
{
if (opt_v)
{
print "reduce(DDDDD)"
print "reduce("DDDDD")"
}
for (i=1; ; i++)
{ ;if (opt_v) print i". DDDDD =|"DDDDD "|"
yyyy = int(DDDDD / 365) - i ;if (opt_v) print i". yyyy =|"yyyy "|"
ddddd = DDDDD - yyyy * 365 ;if (opt_v) print i". ddddd =|"ddddd "|"
cc = int(yyyy / 100) ;if (opt_v) print i". cc =|"cc "|"
leapdays = int(yyyy / 4) ;if (opt_v) print i". leapdays =|"leapdays "|"
cc_leapdays = (cc > 0) ? (int(cc / 4)) : 0 ;if (opt_v) print i". cc_leapdays=|"cc_leapdays"|"
leapdays = leapdays - cc + cc_leapdays ;if (opt_v) print i". leapdays =|"leapdays "|"
ddddd -= leapdays ;if (opt_v) print i". ddddd =|"ddddd "|"
yyyy++ ;if (opt_v) print i". yyyy =|"yyyy "|"
if (ddddd > 0) break
}
if (opt_v)
print "return "yyyy"-"ddddd
return yyyy"-"ddddd
} # function reduce
#----------------------------------------------------------------------#
function shift_ARGV(i,j,k) #
#----------------------------------------------------------------------#
{
k = ARGC
for (i=1; i<=ARGC; i++)
{
if (ARGV[i] == "") # If the argument is empty, see is we
{ # can shift the next one down to it.
for (j=i+1; j<=k; j++)
{
if (ARGV[j] == "") # If the next one is empty, try the one
continue # following that.
ARGV[i] = ARGV[j] # Once we find an argument, move it down,
ARGV[j] = "" # null where it was, decrement arg counter,
break # then do this with the next argument.
}
}
}
for (i=1; i<k; i++) # Adjust ARGC
if (ARGV[i] == "") # If the argument is empty,
ARGC-- # decrement ARGC
return ARGC
} # function shift_ARGV
#----------------------------------------------------------------------#
function show_documentation(MOI, n,line) #
#----------------------------------------------------------------------#
{
n = 0
while (getline <MOI > 0) # Searching ourselves for the doc'n section.
{
#------------------------------------------#
# Until we find the documentation section, #
# keep looking at each line. #
#------------------------------------------#
if (n == 0)
{
if ($0 ~ /^\043 +D O C U M E N T A T I O N/)
{
n = 1
print line
print $0
}
else
line = $0
continue
} #-----------------------------------#
else # Once we find it, print until EOF. #
{ #-----------------------------------#
print
}
} # while (getline <MOI > 0)
if (n == 0) # Means we did not find documentation section.
{
print "NO DOCUMENTATION section found for "MOI" in the",
"current directory (cwd).\nTry again after first",
"changing to the program directory." | "cat 1>&2"
exit 10 # Exit failure
}
exit 11 # Exit failure anyway because we don'y live for this.
} # function show_documentation
#----------------------------------------------------------------------#
function validate_yyyymmdd( \
YYYY,MM,DD, \
yyyy,mm,dd,mm_days,month_names \
) # Calls: leap_year() #
#----------------------------------------------------------------------#
{
if (opt_v)
{
print "validate_yyyymmdd(YYYY,MM,DD)"
print "validate_yyyymmdd("YYYY","MM","DD")"
}
yyyy = YYYY
mm = MM
dd = DD
dd += 0
mm += 0
split("January February March " \
"April May June " \
"July August September " \
"October November December", month_names)
if (mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12)
mm_days=31
else if (mm==4||mm==6||mm==9||mm==11)
mm_days=30
else if (mm==2)
mm_days = (leap_year(yyyy)) ? 29 : 28
else
{
print "Month "MM" is invalid!\n" | "cat 1>&2"
exit 8
}
if (dd > mm_days)
{
print month_names[mm]", "yyyy,
" does not have "dd" days!\n" | "cat 1>&2"
exit 9
}
if (dd < 1)
{
print DD " is an invalid day for any month!\n" | "cat 1>&2"
exit 10
}
return 0
} # function validate_yyyymmdd
#======================================================================#
# D O C U M E N T A T I O N #
#======================================================================#
# #
# Author: Bob Orlando (Bob@OrlandoKuntao.com) #
# #
# Date: July 2, 1995 #
# #
# Program ID: dateplus.awk #
# #
# Usage: [gn]awk -f dateplus.awk -- -bHhjSstuvWwy \ #
# -|+adj yyyymmdd #
# #
# nawk|gawk = Program runs with either. (See "Usage Note:" #
# below for "#!" operation.) #
# -- = Allows AWK to pass script options and args. #
# -b = Basedate for today or yyyymmdd. #
# -H = Full formal documentation (functions only #
# when the current working directory is the #
# program directory). #
# -h = Summary help (Usage). #
# -j = Julian day for today or yyyymmdd. #
# -S = Days since (or until) yyyymmdd (unsigned both). #
# -s = Days since (or until) yyyymmdd (signed future). #
# -t = Tomorrow's date. #
# -u = Basedate of today|yyyymmdd since #
# Jan. 1, 1970--the Unix epoch date #
# (essentially "dateplus -s 19700101"). #
# -v = Verbose output (primarily for development). #
# -W = Date's long weekday #
# -w = Date's abbreviated weekday #
# (see 'Exit Codes' below for -W and -w) #
# -y = Yesterday's date. #
# #
# adj = Adjustment days that may be positive or #
# negative (prefix sign annotation only). #
# By itself (with no yyyymmdd date following, #
# yields an adjusted date that is calculated #
# from today's date. #
# yyyymmdd = Optional date from which the adjusted date #
# is calculated. #
# #
# Usage Note: If your OS recognizes the "#!" (shebang) syntax, #
# you can place a "#!/usr/bin/nawk -f" (or gawk) #
# at the start of this program (as I have) thereby #
# allowing you skip the "[gn]awk -f" during invocation. #
# #
# Purpose: This program calculates a date or dates that is #
# nnnnn days (+ or -) distant from either today's #
# date or another user-supplied date. #
# #
# Description: This program is the Awk equivalent of my C program, #
# dateplus.c. With the exception of -J (capital "J") #
# option and the iterations argument, all of the C #
# program options are available here. This Awk #
# version of the dateplus.c program is supported and #
# maintained as part of my shell library for those #
# sites with limited C-compiler access. #
# #
# 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). #
# #
# Exit Codes: For all options except weekday (-w) #
# Zero = Normal | Success #
# Nonzero = Abnormal | Failure #
# For weekday (-w) option #
# 0-6 = Success (zero-based weekday: Sun = 0) #
# 7+ = Failure #
# #
# 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. All of this is only for technical #
# purists. Most real-world applications will not #
# go back that far. This program's accuracy, #
# then, is sufficient for most purposes. #
# #
# Notes: I am also no mathematician. Neither do I consider #
# myself an AWK expert. If, therefore, any find #
# errors in my code, logic, or computations, please #
# advise me at Bob@OrlandoKuntao.com. Your input #
# is sincerely appreciated. Thank you in advance. #
# #
# +----------------------------------------------------------+ #
# | For modifications, see 'Modified' section in the | #
# | source code immediately following this statement. | #
# +----------------------------------------------------------+ #
# #
# Modified: 2010-03-19 Bob Orlando #
# v2.8 * Bug fix: Added code to reject day '00' #
# supplied by user. #
# #
# 2008-04-06 Bob Orlando #
# v2.7 * Bug fix: Commented out the following line #
# ddddd_to_yyyymmdd function: #
# #
# if (leap_year(yyyy) && i > 2) ddddd++ #
# #
# The line was adding a day if the year #
# is a leap year and the month is after #
# February. This was unnecessary because I #
# already use separate tables for leap and #
# normal years. #
# #
# 2005-02-08 Bob Orlando #
# v2.6 * Bug fix: Changed #
# if (leap_year(yyyy) && mm > 2) ddddd++ #
# to #
# if (leap_year(yyyy) && i > 2) ddddd++ #
# #
#----------------------------------------------------------------------#
|