DATEEXPR(1)

NAME

dateexpr - perform date and time calculations

SYNOPSIS

dateexpr [ -fmt fmt ] expression

DESCRIPTION

dateexpr evaluates an expression, much like expr(1), except that the expression may also involve dates and times. As a simple introductory example, the invocation

	dateexpr today - 1 day
prints yesterday's date. Since the date/time libraries used by dateexpr know about not only the basics of clocks and calendars (``Thirty days hath September...''), but also the more subtle details involving leap years and Daylight Saving Time (and even leap seconds!), it is straightforward to perform computations like the above accurately.

The supported operators are

	* /
	+ -
	< <= > >= = !=
Parentheses may be used to override the default precedence, which otherwise follows the traditional levels (as reflected in the list above).

The terms in an expression may consist of:

Dates and times are relatively free-form, as suggested by the examples above. Notice that fractional seconds are supported. The notation ``nn:nn'' is interpreted as HH:MM; you can use either 0:nn:nn or nn:nn.0 to explicitly force minutes and seconds.

These special terms may also appear:

now
The date and time as of the instant the program is run
today
The date on which the program is run
mtime(file)
The modification time of file
atime(file)
The last-accessed time of file
ctime(file)
The ctime (``inode changed'') time of file

(Currently, the file name operands to the mtime(), atime(), and ctime() operators appear as ``bare words'', but this may change.)

Internally, dateexpr supports two kinds of date/timestamps: relative and absolute. Roughly speaking, date/timestamps that contain a calendar date are absolute, and all others are relative. Relative times can be added and subtracted freely, and added to and subtracted from absolute times. The difference between two absolute times is a relative time. The sum of two absolute times is meaningless and is disallowed.

Certain mixed-mode calculations are also permitted. Integers may be added to or subtracted from date/timestamps; the integer is interpreted as a number of seconds unless suffixed with a unit indicator. Relative timestamps (but not absolute) may be multiplied or divided by integers, yielding relative timestamps.

The relational operators (<, >=, =, etc.) may be applied to pairs of absolute times, to pairs of relative times, or to pairs of integers, but not to any other combinations.

dateexpr attempts to print its output in a format mimicking its input, and with an appropriate amount of precision. The heuristics are not always successful, but the -fmt option can be used to force an explicit output representation.

The exit status is zero if a nonzero time or integer is computed (including as the result of a successful comparison), 1 if a zero result is computed (including as the result of an unsuccessful comparison), and 2 on errors.

OPTIONS

-fmt fmt
Set the output format specifier. For absolute times, the format string is in the style of strftime(3), q.v. (but see below). For integers, the format string is in the style of printf(3). For relative times, an attempt is made to support strftime formats, although this attempt is not always meaningful or successful; more work (and likely some extension) is necessary in this area.
The strftime formats accepted by dateexpr have several extensions:
1. Widths may be specified, in the style of printf. The default width for most specifiers is 02, that is, a minimum width of 2, with 0-padding, for compatibility with strftime(3). But, for example, %1d specifies a minimum width of 1 (and therefore with no padding), %3d specifies a minimum width of 3 with space padding, etc.
2. Decimal fractions are supported. For example, %.2S prints seconds and subseconds, with two digits of precision past the decimal. %.2M prints fractional minutes, where any seconds (and subseconds) information is rolled into the minutes. (That is, the time 1:15 printed as %.2M would yield 1.25. Therefore, if you're printing fractional minutes, you probably don't want to print explicit seconds at all.) Fractions are currently supported for the %d, %H, %M, and %S formats.
-?, -h, -help
Print a brief help message.
-version
Print dateexpr's version number.

EXAMPLES

Compute the day before March 1, 2000, demonstrating that 2000 was a leap year:

	dateexpr 2000-03-01 - 1 day

Compute the number of days between February 28 and March 1, 1900, demonstrating that 1900 was not a leap year:

	dateexpr 3/1/1900 - 2/28/1900

Divide 1 hour by 3, yielding 20 minutes:

	dateexpr 1:00:00 / 3

Compute the author's age:

	dateexpr today - October 2, 1961

See if a file has been accessed since it's been modified:

	dateexpr atime \( file \) \> mtime \( file \)
(The backslashes \ quote the parentheses and greater-than symbol to protect them from interpretation by the shell.)

See how long a command took to execute:

	start=`date`
	long_running_command
	end=`date`
	dateexpr $end - $start

See how long a command took to execute, another way:

	start=`dateexpr now`
	long_running_command
	dateexpr now - $start

See how long a command took to execute, with subsecond resolution:

	start=`dateexpr -fmt %H:%M:%.2S now`
	long_running_command
	dateexpr -fmt %H:%M:%.2S now - $start

Compare two times:

	if dateexpr 0:91 '>' 1:30 > /dev/null; then echo yes; else echo no; fi

BUGS

When adding integers to dates, you probably want the integers to be interpreted as days, not seconds.

Relative times are output in units of at most days, which is awkward if you're computing intervals which amount to years. (You can explicitly divide by 365 if you like, but the output will still be tagged with the word ``days''.)

It's unclear whether nn:nn should be interpreted as HH:MM or MM:SS. (On the other hand, in simple calculations like ``1:01 + 2:02'', it hardly matters.) The fact that nn:nn is interpreted as HH:MM, while nn:nn.nn is interpreted as MM:SS.ff, seems odd.

It is not fully possible to control the output format for relative date/timestamps. Negative relative times are probably not always printed correctly.

Division, especially by large numbers (e.g. greater than 1000) is buggy.

The syntax for the mtime, atime, and ctime operators is awkward and should probably be changed.

Time zones and Daylight Saving Time are not perfectly handled yet. (Nor are leap seconds, though the attempt is valiant.)

Calendars other than Gregorian are not handled yet.

Years 0 or B.C. are not properly handled yet.

When rounding times for printout, if 0.99999... seconds has to be rounded up to 1.000 second, it is not always possible to propagate the carry up through the %S, %M, %H, %d, %m, and %Y values.

FILES

/usr/local/lib/leapsec.tab leap second information

SEE ALSO

expr(1), strftime(3), ctime(3), printf(3)

HISTORY

This documentation corresponds to version 1.6 of the program.

See http://www.eskimo.com/~scs/src/#dateexpr for possible updates.

COPYRIGHT

Copyright 2002-2003
This program and its documentation may be freely redistributed and altered and used at will, as long as this notice remains attached and as long as any modifications are marked as such.

AUTHOR

Steve Summit, scs@eskimo.com