rod@pecnos.UUCP (Robert O. Domitz) (02/20/86)
I have found this program useful over the past eight months. About four months ago, I was moved to a XELOS system (our proprietary version of System V) and found the format options of the 'date(1)' routine. To make the program more useful, I modified Dan LaLiberte's set of options to more closely imitate the set of options in the 'date(1)' routine. Although I've been using this now for about three months in this form, my workload has finally slowed down enough to allow me the time to post this to net.sources. I would like to thank Dan LaLiberte for posting his original routine. To give credit where credit is due, here are excerpts from the header of the original posting: """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Path: petsd!vax135!houxm!ihnp4!inuxc!pur-ee!uiucdcs!seefromline From: liberte@uiucdcs.Uiuc.ARPA Subject: date+ - add specified time to date Message-ID: <12600026@uiucdcs> Date: Fri, 12-Jul-85 00:23:00 EDT Date-Received: Fri, 12-Jul-85 20:07:06 EDT The recent date-oriented postings prompted me to finally get this out. What prompted its creation was the fact that I had to write yet another single-purpose add-something-to-the-current-date program. Also, I noticed a recent posting of a script that used `at` with a "+ #" option that we do not have. Now you can do things like: at `date+ 2 hours` < reminder or set lastmonth = `date+ -1 month "%y.%n"` Date+ has more options than I know what to do with, but it's the kind of program that needs options. So send me your suggestions. It is written for Berkeley 4.2. Daniel LaLiberte 217-333-8426 University of Illinois, Urbana-Champaign Department of Computer Science 1304 W Springfield Urbana, IL 61801 liberte@uiucdcs.Uiuc.ARPA ihnp4!uiucdcs!liberte """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # date+.1 date+.c echo x - date+.1 cat > "date+.1" << '//E*O*F date+.1//' .TH DATE+ 1 .UC 4 .SH NAME date+ \- print date plus specified time .SH SYNOPSIS .B date+ [ .I number unit ]... [ .I format ] .SH DESCRIPTION The .I date+ command increments the current time by the specified amount of time given as several .I number unit pairs. The .I unit may begin with .B sec min hour day week mon or .B year. Trailing characters are ignored. The positive or negative floating point .I number is truncated if the unit is month or year. .de mI .ti -4 \\$1\ \ .. .PP The optional .I format specifies how to print out the date and time information. A percent sign introduces a conversion operator; the next character specifies the desired conversion. Other characters are simply printed. The conversion characters and their meanings are: .sp .in +6 .mI n insert a newline character. .mI t insert a tab character. .mI S seconds. .mI M minutes. .mI H hours. .mI T time as HH:MM:SS. .mI d day number within the month (01-31). .\" .mI D .\" day number without leading zero. .mI m month number (01-12). .mI h month name (3 character). .mI y year number - 1900. .mI w weekday number (0 is Sunday). .mI a weekday name (3 character). .mI D date as mm/dd/yy. .mI j day number within the year (1-365). .mI Z number of seconds since 00:00:00 GMT Jan 1, 1970. .in -6 .ne 7 .PP The default format is .ti +2 .nf "%H:%M %h %d" .fi which is suitable as input to the .I at (1) command. Note that if the format string has any special characters (including spaces) then they must be protected by quoting. .SH EXAMPLE .nf at `date+ 2 hours` echo Time for a break > /dev/ttyme ^D date+ -1 month "%y.%n" # Return yy.mm for previous month .fi .SH SEE\ ALSO .I at (1), .I date (1) .SH AUTHOR Daniel LaLiberte, University of Illinois, Urbana-Champaign .br System V version: Robert O. Domitz, Concurrent Computer Corporation, Tinton Falls, NJ. .SH BUGS Dates that don't exist, e.g., Feb 31, can be produced by adding months or years. Producing dates before Jan 1, 1970 will give strange results. //E*O*F date+.1// echo x - date+.c cat > "date+.c" << '//E*O*F date+.c//' /* date+ - add specified time to current date */ /* Please send additions, bug fixes, portifications, etc. to: * * Daniel LaLiberte * ihnp4!uiucdcs!liberte * University of Illinois, Urbana-Champaign * Department of Computer Science */ /* This is written for BSD42 */ /* This was revised for SYSTEM V by: * * Robert O. Domitz * ...!vax135!petsd!pecnos!rod * Concurrent Computer Corporation * 106 Apple Street * Tinton Falls, NJ 07724 */ #include <stdio.h> #include <time.h> long tloc; long time(); char *ctime(); struct tm *localtime(); struct tm *ts; double atof(); int argc; /* global argument passing */ char **argv; main (Argc, Argv) /* return time + 1st arg hours */ int Argc; char *Argv[]; { argc = Argc; argv = Argv; incrdate(); printdate(); } /* main */ incrdate() /* increment date from arguments */ { static char *unit[] = { "sec", "min", "hour", "day", "week", "mon", "year", "" }; static int conv[] = /* conversion factor */ { 1, 60, 3600, 86400, 604800, 0, 0 }; int i; double value; long total; /* cummulative total increment in whole seconds */ double monthincr = 0.0, /* store increment of month and year */ yearincr = 0.0; /* since months and years are not uniform */ time(&tloc); /* current time */ argc--; argv++; while (argc && ((**argv == '.') || (**argv == '-') || (**argv == '+') || (**argv >= '0' && **argv <= '9'))) { value = atof(argv[0]); /* printf("%s = %f", argv[0], value); */ argv++; argc--; if (argc == 0) missing(); else { /* search for unit */ for (i = 0; (i < 7) && (0 != strncmp(argv[0], unit[i], strlen(unit[i])));) i++; if (i == 7) missing(); else { argv++; argc--; if (i < 5) value *= conv[i]; if (i == 5) monthincr += value; if (i == 6) yearincr += value; } /* printf(" %s (%f seconds)\n", unit[i], value); */ } total += value; } tloc += total; ts = localtime(&tloc); ts->tm_mon += monthincr; ts->tm_year += yearincr; } /* getincr */ missing() { fprintf(stderr, "date+: missing unit\n"); exit (1); } printdate() { char *format; static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static char *day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; if (argc == 0) { /* put default format on argv */ argv[0] = "%H:%M %h %d"; argc++; } while (argc > 0) { format = argv[0]; while (*format) { if (*format != '%') putchar(*format); else if (format[1]) switch(*++format) { case 'n': putchar ('\n'); break; case 't': putchar ('\t'); break; case 'S': printf("%02d", ts->tm_sec); break; case 'Z': printf("%d", tloc); break; case 'M': printf("%02d", ts->tm_min); break; case 'H': printf("%02d", ts->tm_hour); break; case 'T': printf("%02d:%02d:%02d", ts->tm_hour, ts->tm_min, ts->tm_sec); break; case 'd': printf("%02d", ts->tm_mday); break; /* case 'D': printf("%d", ts->tm_mday); break; */ case 'm': printf("%02d", ts->tm_mon + 1); break; case 'h': printf("%s", month[ts->tm_mon]); break; case 'y': printf("%02d", ts->tm_year); break; case 'w': printf("%1d", ts->tm_wday); break; case 'a': printf("%s", day[ts->tm_wday]); break; case 'D': printf("%02d/%02d/%02d", ts->tm_mon + 1, ts->tm_mday, ts->tm_year); break; case 'j': printf("%d", ts->tm_yday); break; default: fprintf(stderr, "date+: Bad format character: '%c'\n", *format); exit(1); } format++; } /* while (*format) */ argc--; argv++; if (argc > 0) putchar(' '); } /* while (argc > 0) */ putchar('\n'); } /* printdate */ //E*O*F date+.c// echo Possible errors detected by \'wc\' [hopefully none]: temp=/tmp/shar$$ trap "rm -f $temp; exit" 0 1 2 3 15 cat > $temp <<\!!! 104 364 1995 date+.1 219 542 3916 date+.c 323 906 5911 total !!! wc date+.1 date+.c | sed 's=[^ ]*/==' | diff -b $temp - exit 0