Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Date Calculations

0 views
Skip to first unread message

Ernest Simard

unread,
Jan 20, 1999, 3:00:00 AM1/20/99
to
Hi,
Anybody have any scripts (shell, nawk etc) that can take two dates and
return the number of days in-between?

Thanks Ernie

Howard Bryden

unread,
Jan 24, 1999, 3:00:00 AM1/24/99
to
I fancy you'll have to do this with a C program built around the difftime() routine. I've implemented this capability (under HPUX 10.20) as a ksh function "wrapper" around the executable:

#
# *** Function to interface the timediff program.
# $* = Command line arguments for the program.
#
# -d dlt Delimiter character separating each format string in the list passed by the -m option. Comma is the default.
# -m list List of format mask strings to be assembled into a template file before running the program.
# -n The list passed by the -m option is the name of a variable to be dereferenced.
#
function timediff {
typeset PATH=/usr/bin
typeset OPT masks=''
typeset -L1 dlt=','
typeset -i deref=0
#
while getopts :d:m:n OPT
do case $OPT in
d) dlt=$OPTARG ;;
m) masks=$OPTARG ;;
n) deref=1 ;;
:) print -u2 "$0: -$OPTARG needs value"
return 2 ;;
\?) print -u2 "$0: Bad option -$OPTARG"
return 2 ;;
esac
done
shift $(( OPTIND - 1 ))
#
# Break up the format masks and write them into a scratch template file as ultimately demanded by the getdate(3C) routine.
#
typeset datemsk=$(mktemp)
trap "rm -f '$datemsk' 2>$_NULL" EXIT
(( deref )) && eval masks=\"$masks\"
print - "$masks" | tr "$dlt" "$NL" >"$datemsk"
DATEMSK=$datemsk $SW/bin/timediff "$@"
#
return $?
}

/* -----------------------------------------------------------------------------
*
* Program timediff.c
*
* Use: To determine the time difference between two date/time strings.
*
* Construction: cc +DAportable -o timediff -Osn timediff
*
* Command line: timediff [-u unit] [-s n] time1 time2
*
* -s n Number of decimal places by which to report the difference if the unit (as per -u) is not "s"
* (i.e. integral number of seconds).
* The default is 2.
*
* -u unit Time units in which to report the difference:
* "s" seconds (default),
* "m" minutes,
* "h" hours,
* "d" days,
* "w" weeks,
* "y" years.
*
* time1 First date/time string.
* time2 Second date/time string.
*
* The formats for time1 and time2 are expected to be in a template "file" named via the environment
* variable DATEMSK as per the manpage for getdate_r().
*
* Algorithm: Use getdate_r(3C) to convert strings time1 and time2 with reference to their respective format masks.
* Use difftime(3C) to calculate the time difference in seconds.
* If required, scale this value as set by the -u and -s options.
*
* Response value: 255 unrecognized option,
* EINVAL bad option value or other than 2 arguments,
* 1..8 as returned from getdate_r(),
* else as returned by errno.
*
* -----------------------------------------------------------------------------
*
* Included files:
*
* errno.h Error response values.
* stdio.h I/O environment.
* time.h Required by getdate_r() and difftime().
*
* External variables:
*
* argc,argv Commandline argument count & strings.
* errno Status value.
* optarg Value supplied with an option.
* optind Index of an option in argv.
*
* Local variables:
*
* calendar Calendar time value returned by mktime().
* dtime Time difference returned by difftime().
* fmt Format model for sprintf().
* getdate_err Status returned by getdate_r().
* i, iret Temporaries.
* msg Message text.
* name Name of this program.
* factor Value by which to divide the time difference value.
* scale No. decimal places to report on size.
* sec Number of seconds in the time difference.
* time Time structures returned by getdate_r().
*
* Definitions:
*
* SCALE Default value for the -s option.
*
* Files used:
*
* stderr Error messages.
* stdout Time difference value.
*
* -----------------------------------------------------------------------------
*
* Req'd functions:
*
* atoi String -> integer.
* basename Extract the base portion of a name.
* difftime Calculate difference between two time_t's.
* getdate_r Date/time value -> struct tm.
* getopt Parse commandline options.
* exit Set the exit status value.
* fprintf Print to a specific FD.
* mktime struct tm -> time_t.
* printf Print a string to standard output.
* sprintf Print into a string variable.
* strerror Produce a text string from an error number.
*
* -----------------------------------------------------------------------------
*/
#include <stdio.h>
#include <time.h>
#include <sys/errno.h>

#define SCALE 2

extern int errno;
extern int optind;
extern char *optarg;

main( argc, argv )
int argc;
char *argv[];

{ int iret, scale = SCALE, factor = 1;
char *name = basename(argv[0]);
/*
* Parse the options.
*/
errno = 0;
while ((iret = getopt(argc, argv, "s:u:")) != EOF) {
switch( iret ) {
case 's': scale = atoi( optarg );
break;
case 'u': switch( *optarg ) {
case 's': factor = 1;
break;
case 'm': factor = 60;
break;
case 'h': factor = 60 * 60;
break;
case 'd': factor = 60 * 60 * 24;
break;
case 'w': factor = 60 * 60 * 24 * 7;
break;
case 'y': factor = 60 * 60 * 24 * 365;
break;
default: fprintf( stderr, "%s: Time unit '%s' invalid\n", name, optarg );
exit( EINVAL ); };
break;
case '?': exit( 255 ); }; };
/*
* Must have precisely two arguments.
*/
if (argc-optind != 2) {
errno = EINVAL;
fprintf( stderr, "%s: %s\n", name, "Must have two date/time strings" ); }
else {
int i, getdate_err;
time_t calendar[2];
struct tm time[2];
double dtime;

for( i=0; i<2; i++ ) {
if (getdate_r( argv[optind+i], &time[i], &getdate_err ) == 0) {
calendar[i] = mktime( time[i] );
if (errno != 0) fprintf( stderr, "%s: %s\n", name, strerror(errno) ); }
else {
char *msg;
switch( getdate_err ) {
case 1: msg = "DATEMSK environment variable null or undefined."; break;
case 2: msg = "Template file cannot be opened."; break;
case 3: msg = "Cannot get file status."; break;
case 4: msg = "Template file not a regular file."; break;
case 5: msg = "Template file read error."; break;
case 6: msg = "Not enough memory."; break;
case 7: msg = "No match in template file."; break;
case 8: msg = "Invalid date/time specification."; break;
default: msg = "Undefined error from getdate()."; break; };
fprintf( stderr, "%s: %s\n", name, msg );
exit( getdate_err ); } };

dtime = difftime( calendar[0], calendar[1] );
if (factor == 1) {
long sec = dtime;
printf( "%d\n", sec ); }
else {
char fmt[10];
sprintf( fmt, "%%.%df\n", scale );
printf( fmt, dtime / factor ); }; }

exit( errno );
}

--
Oracle DBA / HPUX Sysadmin | Rocky: "We're going to have
Comalco Minerals & Alumina, | to think!"
Weipa, AUSTRALIA 4874 | Bullwinkle: "There must be
Tel 61-7-40698711 Fx.61-7-40698951| an easier way than that."

John DuBois

unread,
Jan 25, 1999, 3:00:00 AM1/25/99
to
In article <785f5a$7mf$1...@hades.csu.net>,

Ernest Simard <Sim...@Sonoma.Edu> wrote:
>Anybody have any scripts (shell, nawk etc) that can take two dates and
>return the number of days in-between?

Sure. See the function diffdays in ftp://ftp.armory.com./pub/lib/ksh/days

John
--
John DuBois spc...@armory.com. KC6QKZ http://www.armory.com./~spcecdt/

0 new messages