Problem with Time>asSeconds

86 views
Skip to first unread message

Louis LaBrunda

unread,
Aug 15, 2011, 2:14:53 PM8/15/11
to va-sma...@googlegroups.com
Hi All,

I have just traced a problem with VA Smalltalk V8.0.3 to a change between it (and I guess other versions) and VAST 5.5.2 where the Time>asSeconds method now answers a rounded up number of millisecondsFromMidnight and not the current number of secondsFromMidnight as V5.5.2 did (see code below). In V5.5.2 there were no milliseconds, just seconds. I have lots of code that expects #asSeconds to be the current number of seconds from midnight and not a rounded up value to the next second.  This is the cause of my apparent not dispatching problem posted in another thread.  I will explain more in that thread at a later time.

I don't see a good reason for the rounding up, so I would prefer it if the rounding was just removed in V8.5.  If anyone needs the current rounded up value, maybe a new method could be added like #asRoundedSeconds.

What does everyone else think?

Thanks,

Lou


V8.0.3:
asSeconds
"Answer an Integer that is the number of
seconds since midnight of the receiver."

^millisecondsFromMidnight + 500 // 1000

V5.5.2:
asSeconds

"Answer an Integer that is the number of
seconds since midnight of the receiver."

^secondsFromMidnight

Wayne Johnston

unread,
Aug 16, 2011, 9:01:11 AM8/16/11
to va-sma...@googlegroups.com
No expert here but philosophically I agree it should truncate not round.

Marten Feldtmann

unread,
Aug 16, 2011, 11:39:39 AM8/16/11
to va-sma...@googlegroups.com
Please remember, that this message is now nearly 10 year old - with this source code .... and I get the feeling, that using the method in the way Louis did in 5.5.2 is not ok. Actually I'm very surprised, that an algorithm fails because of this change - this does not seem to be a stable algorithm for me.

John O'Keefe

unread,
Aug 16, 2011, 3:42:00 PM8/16/11
to va-sma...@googlegroups.com
Lou -

Can you explain a bit more about why your algorithm fails? 

Philisophically I agree with Wayne -- I would expect to get the same answer from asSeconds as I would get from hours * 60 + minutes * 60 + seconds. However, given the age of the method and the stability issues we have had in the past with our various time-related classes, I am reluctant to make a change without a strong rationale.

John

Louis LaBrunda

unread,
Aug 16, 2011, 5:24:07 PM8/16/11
to va-sma...@googlegroups.com
Hi John,

The code looks something like this:

lastTime := Time now asSeconds.
nextMinute := ((lastTime // 60) + 1) * 60.
[
currentTime := Time now asSeconds.
(currentTime >= lastTime) & (currentTime < nextMinute).
  ] whileTrue: [(Delay forMilliseconds: 500) wait].

The code is in a larger loop that I don't show.  When it falls out of the #whileTrue: loop it is expected to be within the next minute.  With the rounding up of #asSeconds, we can still be in the same minute, all be it close to the end of the minute.

The result of the problem wasn't terrible but it wasn't good either.  I was keeping some activity counts by one minute intervals.  Because of the problem those counts are askew again not terrible but bad enough.

Finding the problem wasn't fun either.  I didn't expect the public #asSeconds method of #Time to change how it worked from one version to another.  I know public methods can change, when the class changes and Time did get milliseconds added to it but I would have kept #asSeconds working as it was and added another method if the rounded value of seconds was needed.

The problem is fixed easy enough for this code.  But I worry about other uses of #asSeconds and the problems that can be hiding out there, of mine and others.

For example:

EmTimeStamp class now

now
"Create a new time stamp with the current date and time. This can be incorrect
on some platforms if Time class>>#dateAndTimeNow does not ultimately use
a primitive that atomically answers the current date and time. If for example
the method just sends Date class>>#today and Time class>>#now, and the former
is sent before midnight and the latter is sent on or after midnight, the answer will be
out by twenty-four hours."

| dateAndTime |
dateAndTime := Time dateAndTimeNow.
^self new: (dateAndTime at: 1) asSeconds + (dateAndTime at: 2) asSeconds +
(self usingGMT
ifTrue: [3600 * self timeZonesFromGMT]
ifFalse: [0])

It seems to me that the above code (that is not mine) will fail even if a primitive is used if the time is just before midnight as the #asSeconds will round past midnight.

I also think this code (also not mine) might have problems if the passed in time rounds up to a time larger than now or maybe even vise versa.

StsPowerTools class

addTimeoutAt: aTime
receiver: receiver
selector: selector
clientData: clientData

| now then interval |
now := Time now asSeconds.
then := aTime asSeconds.
interval := then - now.
now >= then
ifTrue: [interval := interval + 86400].
self
addTimeout: interval * 1000
receiver: receiver
selector: selector
clientData: clientData

Also:

Time>putObjectOn: aStream
"Write into @aStream the byte representation of the receiver."

aStream nextPutIntegerAsFourBytes: self asSeconds

uses #asSeconds.  I'm not sure if the rounding could cause a problem or not.  I guess it depends where the data is going and if upon reading it in it is expected to be the same as was written.

Also please note that the display of a time value does not reflect the rounding up of the seconds:

((Time now) hours: 16 minutes: 37 seconds: 59 milliseconds: 600) asMilliseconds
59879600

(Time fromMilliseconds: 59879600)
4:37:59 PM

Time fromSeconds: ((Time fromMilliseconds: 59879600) asSeconds)
4:38:00 PM

Please don't take the above as a request to round up the seconds when displaying a time object.  I just think that if the rounding was valuable, it would be used there.

Maybe I'm wrong about this as my friend Marten (who I respect greatly) suggests but I don't think so and I am curious if anyone out there has code that depends upon #asSeconds rounding the seconds?

Lou

SebastianHC

unread,
Aug 16, 2011, 9:19:18 PM8/16/11
to va-sma...@googlegroups.com
Hi Louis,

if you are still in the mood for browsing through your code and eventual
drawbacks due to your update, I would like to point you on one little change
that I had similar problems with.

The method Number>>#abtAsInteger changed from down to up rounding. It's is
also in the documentation but you never know if someone in the past hacked
around it, or hacks might rely on this. Especially when you have general
coding handling "Number"s.


Check this out: (Number fromString: '0.7') abtAsInteger and loadthe
different versions of abtAsInteger:

NEW:
abtAsInteger
"Answer an integer which is nearest to the receiver."

^self rounded

OLD:
abtAsInteger

^self truncated


Even if this is a documented change it is sometimes hard to find those,..
especially when it comes to XML and other file processings...


Have fun ;-)
Sebastian

--
View this message in context: http://forum.world.st/Problem-with-Time-asSeconds-tp3745290p3748889.html
Sent from the Instantiations mailing list archive at Nabble.com.

Louis LaBrunda

unread,
Aug 17, 2011, 10:30:21 AM8/17/11
to va-sma...@googlegroups.com
Hi Sebastian,

I can see where the change you point out could cause some problems.  In that case I think I like the rounding version over the truncated one but that's just me.  The problem would be in not knowing about the change.  One could have used #rounded or #truncated in the first place and not had any problem with the change to #abtAsInteger.

At least when working with numbers, especially floats, one expects that when going to integers there is a choice between rounding and truncating.  With the #Time class, the original didn't have fractions of seconds and there was no reason to think about rounding or truncating.  When milliseconds were added, things changed.

I think rounding the milliseconds to seconds in #asSeconds was a bad choice.  It was guaranteed to break someones code.  Truncating wouldn't break any code.  If anyone needed rounding (which I find had to believe) it would be in new code and easily dealt with.

This brings us to John's problem.  Put #asSeconds back to the way it was, fixing broken code that I think I have shown exists and possibly breaking newer code that depends upon rounding, that so far no one has shown exists.  Or, leave things as they are, hoping the problems with rounding get found and fixed and not breaking the code that depends on rounding if any exists.

There is also the question of what other Smalltalks do.  I don't suggest the answer be the primary factor in John's choice but it is one thing to consider.  Would those of us who have access to other Smalltalks, please tell us what they do.  I looked at Squeak 4.1, it keeps time as two values of seconds and nanoseconds.  Its #asSeconds method returns seconds, no rounding.  My guess is that Pharo, a descendant of Squeak, which Seaside is build on, does the same as Squeak.

Lou

Louis LaBrunda

unread,
Aug 30, 2011, 9:50:50 AM8/30/11
to va-sma...@googlegroups.com
Hi All,

One hopefully last reason to truncate (and not round) #millisecondsFromMidnight in #asSeconds.  Code that wants milliseconds truncated to seconds would look something like:

aTime asMilliseconds // 1000.

But if in some future release microseconds are added to time (as milliseconds were and other Smalltalk have) the #asMilliseconds method might follow the same rounding pattern and answer a rounded microseconds breaking the above fix to the rounded #asSeconds problem.

Lou

Reply all
Reply to author
Forward
0 new messages