Page 1 of 1

Adding and subtracting timestamps

Posted: Fri Aug 07, 2009 11:45 am
by ConvertFromOldNGs
by Shane Carter >> Mon, 6 Dec 1999 23:08:47 GMT

Hi all.
I'm trying to add and subtract one timestamp from another and was wondering if anyone knew of any methods written to do this. Also, to divide a timestamp by an integer value, to get an average timestamp value.

I can add and subtract time values from timestamps, but one timestamp from another is a different story.

Thanks for your help,
Shane.

Re: Adding and subtracting timestamps

Posted: Fri Aug 07, 2009 11:45 am
by ConvertFromOldNGs
by Krull >> Tue, 7 Dec 1999 2:15:02 GMT

Hi Shane,

A JADE timestamp is intended to store an absolute point in time. The difference between two timestamps is not a timestamp, it is something like an 'Interval' or 'Duration'. In order to represent the difference between two points in time with the same granularity as a timestamp you either need to either store the difference in milli-seconds (a signed 32 bit integer can only represent approx 24 days) or store the number of days in one attribute and fraction of a day in a separate attribute. You could implement your own Interval data type as a Jade class or you could put that little used primitive type: Point to use as a container to represent a time interval; eg. store days in x and time in y. Either way, you would need to implement methods to a) subtract two timestamps giving an 'interval' b) Add or subtract an 'interval' to/from a timestamp giving another timestamp. Someone out there may have already implemented some form of 'Interval' data type but I would suggest that you submitt an NFS requesting support for this in the product.

The problem of averaging a series of timestamps is a bit trickier but is not too hard if you take adavantage of the ability to add time values to a timestamp to consolidate the time parts.

Re: Adding and subtracting timestamps

Posted: Fri Aug 07, 2009 11:45 am
by ConvertFromOldNGs
by John Porter >> Thu, 9 Dec 1999 5:02:02 GMT

Averaging Times is not difficult:

avgTimes(ta,tb:Time):Time;
begin
return ((ta.Integer+tb.Integer)/2).Time;
end;

This is easily modified for differences instead of averages.

Averaging TimeStamps is a bit more involved, but still not too bad:

avgTimeStamps(tsa,tsb:TimeStamp):TimeStamp;
constants
MilliSecsInDay=86400000;
vars
tsc:TimeStamp;
ra,rb,rc:Decimal[23,10];
begin
// convert timestamps to days and fractions thereof
ra:=tsa.Date.Decimal+(tsa.Time.Integer/MilliSecsInDay);
rb:=tsb.Date.Decimal+(tsb.Time.Integer/MilliSecsInDay);
// average them
rc:=(rb+ra)/2;
// the number to the left of the decimal point is days
tsc.setDate(rc.Integer.Date);
// the number to right of decimal point is time
tsc.setTime(((rc-rc.Integer)*MilliSecsInDay).rounded.Time);
return tsc;
end;

Again, easily modified to subtract instead of average. You could
still pass back the TimeStamp, using tsc.Date.Integer as elapsed days instead of a date. With Decimal handling up to 23 significant digits,
you could add up lots of TimeStamps before having to sacrifice millisecond precision. Today's date is only a 7-digit number.

Cheers,
John P

Re: Adding and subtracting timestamps

Posted: Fri Aug 07, 2009 11:45 am
by ConvertFromOldNGs
by Krull >> Thu, 9 Dec 1999 22:14:33 GMT
You could still pass back the TimeStamp, using tsc.Date.Integer as elapsed days instead of a date. With Decimal handling up to 23 significant digits,
you could add up lots of TimeStamps before having to sacrifice millisecond precision. Today's date is only a 7-digit number.

You are right you could store a time-interval in a timestamp, simply because it has sufficiently sized attributes to represent the 'state' of an interval. However, it will not provide the correct behaviour for a timestamp in that the date attribute contains elapsed days rather than a date value; you would need to be careful where ever such a pseudo timestamp was used. If your application requirements for computing date-time intervals are fairly low and you don't require a reusable solution, then you could represent an interval (the difference between two timestamps) as a decimal. I think this is a more acceptable compromise when you consider timestamp operations such as add or subtract interval. If your representation for an interval was a timestamp then the method signatures would need to take a timestamp eg. TimeStamp::addInterval(interval : TimeStamp) , which is misleading since you can't correctly pass it a true timestamp value. The alternative TimeStamp::addInterval(interval : Decimal) is slightly better but not ideal. I would prefer: TimeStamp::addInterval(interval : Interval), where interval is a user defined 'abstract data type' that encapsulates the state and behaviour of a time-interval. The implementation of a transient Interval class is straightforward;such a type could then be used in various TimeStamp, Date and Time operations. It would be nice to be able to define an Interval primitive-type (in a user schema), which would avoid the need to create and delete transient instances for computational purposes, but we can't do that just yet.

Note: that a day-time interval is a standard SQL type and most object frameworks provide some equivalent e.g. the ODMG type heirarchy has an Interval type and the MickeySoft MFC class hierarchy has a CTimeSpan class to do this job.

Re: Adding and subtracting timestamps

Posted: Fri Aug 07, 2009 11:45 am
by ConvertFromOldNGs
by Robert Barr >> Fri, 10 Dec 1999 0:16:24 GMT

Here's a simple timestamp subtract method. An interval in milliseconds
is returned as a decimal, which should provide sufficient precision for most applications outside astrophysics calculations.



diff(ts:TimeStamp) : Decimal ;

// Calculate the difference between two timestamp values
// Returns 'days' and time difference in milliseconds
// Value returned will be positive (always taking
// smaller value from larger)

vars
d1, d2 : Date;
t1, t2 : Time;
days:Integer;begin


// make sure we take the smaller value from the larger

if self > ts then
d1 := self.Date;
d2 := ts.Date;

t1 := self.Time;
t2 := ts.Time;
else
d2 := self.Date;
d1 := ts.Date;

t2 := self.Time;
t1 := ts.Time;
endif;

days := d1 - d2; // difference in dates

return (Millisecs_per_day * days).Decimal + // days component
(t1 - t2).Decimal ; // and time

end;