Issue 254 in glassdb: DateAndTimes don't compare correctly

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Issue 254 in glassdb: DateAndTimes don't compare correctly

glassdb
Status: Accepted
Owner: [hidden email]
Labels: Type-Defect Priority-Medium GLASS-Server Version-1.0-beta.8.6

New issue 254 by [hidden email]: DateAndTimes don't compare correctly
http://code.google.com/p/glassdb/issues/detail?id=254

for discussion see:

   http://forum.world.st/DateAndTime-problem-td3394257.html

the basic example is:

With the following change to DataAndTime:


   DateAndTime class>>secondsSince2001

        "^DateTime now asSecondsGmt - 3155760000."
        ^ (System _timeGmtFloat - 978307200) asScaledDecimal: 3.

the following doesn't behave as expected:


| date date2  |
date :=  DateAndTime now.
date2 :=  (DateAndTime fromString: (date printString)).
date = date2


Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

NorbertHartl
Ok,

this means it takes a while? :) In the meantime I try if I can get away with

executionTime := DateAndTime fromString: (DateAndTime now printString).

Now I shouldn't forget my sun glasses when going to work :)

Norbert

Am 22.03.2011 um 18:54 schrieb [hidden email]:

> Status: Accepted
> Owner: [hidden email]
> Labels: Type-Defect Priority-Medium GLASS-Server Version-1.0-beta.8.6
>
> New issue 254 by [hidden email]: DateAndTimes don't compare correctly
> http://code.google.com/p/glassdb/issues/detail?id=254
>
> for discussion see:
>
>  http://forum.world.st/DateAndTime-problem-td3394257.html
>
> the basic example is:
>
> With the following change to DataAndTime:
>
>
>  DateAndTime class>>secondsSince2001
>
> "^DateTime now asSecondsGmt - 3155760000."
> ^ (System _timeGmtFloat - 978307200) asScaledDecimal: 3.
>
> the following doesn't behave as expected:
>
>
> | date date2  |
> date :=  DateAndTime now.
> date2 :=  (DateAndTime fromString: (date printString)).
> date = date2
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

glassdb
In reply to this post by glassdb
Updates:
        Status: Fixed

Comment #1 on issue 254 by [hidden email]: DateAndTimes don't compare  
correctly
http://code.google.com/p/glassdb/issues/detail?id=254

If you look closley:


| date date2  |
date :=  DateAndTime now.
date2 :=  (DateAndTime fromString: (date printString)).
{ date. date2. date = date2}

results in:
  anArray( 2011-03-22T11:49:51.581-07:00, 2011-03-22T11:49:51.581-07:00,  
false)

which tells us that the printStrings are the same, so the instances of  
ScaledDecimal are equal (for all intents and purposes) ... but the  
implementation of ScaledDecimal>>#= is ah, quirky and two ScaledDecimals  
that print the same don't necessarily compare the same and this behavior  
is "traditional" in that that's the way most implementations work:)

So in order to get ScaledDecimals to compare equal when they compare equal,  
you have to round to your desired precision, so DateAndTime  
class>>secondsSince2001 would look like this:

secondsSince2001

        "^DateTime now asSecondsGmt - 3155760000."
        ^ ((System _timeGmtFloat - 978307200) roundTo: 1/1000) asScaledDecimal: 3.

Since this is the "expected" behavior for 2.0, there is no bug ... In 3.0  
the GemStone ScaledDecimals that print the same _will_ compare_ equal!




Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

Dale Henrichs
In reply to this post by NorbertHartl
On 03/22/2011 11:11 AM, Norbert Hartl wrote:
> Ok,
>
> this means it takes a while? :)

Well, sort of... it means that I wasn't able to give you an immediate
solution and I didn't want to forget about it ... It is unreliable for
me to leave messages unread in my mail readers (an accidental mark all
as read erases everything), so I use the Issue Tracking system as my
todo list:)

I did take a look and you should have already seen my answer:)

 > In the meantime I try if I can get away with
>
> executionTime := DateAndTime fromString: (DateAndTime now printString).

That was the first thing I thought of, too:), but you can round the
float to the right precision and then create a ScaledDecimal:)

You could do the printString trick to compare the DateAndTimes, too ...
it probably depends upon where you want to put the hack...

>
> Now I shouldn't forget my sun glasses when going to work :)
>
> Norbert
>
Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

NorbertHartl
In reply to this post by glassdb

Am 22.03.2011 um 19:56 schrieb [hidden email]:

Updates:
Status: Fixed

Comment #1 on issue 254 by [hidden email]: DateAndTimes don't compare correctly
http://code.google.com/p/glassdb/issues/detail?id=254

If you look closley:


| date date2  |
date :=  DateAndTime now.
date2 :=  (DateAndTime fromString: (date printString)).
{ date. date2. date = date2}

results in:
anArray( 2011-03-22T11:49:51.581-07:00, 2011-03-22T11:49:51.581-07:00, false)

which tells us that the printStrings are the same, so the instances of ScaledDecimal are equal (for all intents and purposes) ... but the implementation of ScaledDecimal>>#= is ah, quirky and two ScaledDecimals that print the same don't necessarily compare the same and this behavior is "traditional" in that that's the way most implementations work:)

So in order to get ScaledDecimals to compare equal when they compare equal, you have to round to your desired precision, so DateAndTime class>>secondsSince2001 would look like this:

secondsSince2001

"^DateTime now asSecondsGmt - 3155760000."
^ ((System _timeGmtFloat - 978307200) roundTo: 1/1000) asScaledDecimal: 3.

Since this is the "expected" behavior for 2.0, there is no bug ... In 3.0 the GemStone ScaledDecimals that print the same _will_ compare_ equal!

Does this mean that the ScaledDecimal>>= is implemented differently. The effect is that if you create a ScaledDecimal it compiles to numerator and denominator. The equals check just compares those two values it will report false if they are different. So in my case there were different numerator and denominator that caculate to the same value at the given precision and therefor result in the same printString. I'm not sure if roundTo: will automatically lead to the same numerator and denominator in every case. Either I need this assurance or a better ScaledDecimal>= implementation. 

What do you think?

Norbert
Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

Dale Henrichs
Norbert,

I am not a mathematician, so I can't guarantee anything. I was under the
impression that rounding by 1/1000 would result in an exact fraction for
the ScaledDecimal which would imply that the same fraction would be used
when the ScaledDecimal was created from a string ...

Of course implementations hit corner cases. The only way to absolutely
certain that the a DateAndTime created from a String will match the
original DateAndTime is to use a String to create them both:

   DateAndTime fromString: DateAndTime now asString

We figured that the roundTo: would work, but I figured that a
ScaledDecimal would work:) earlier.

As I mention in the email, you could use the printString in your
comparison instead of #= and then there would be no need to round the
ScaledDecimal ...

You could also change the implemention of fromString: to avoid
ScaledDecimal, but I'm not sure that would solve your problem without
having to fudge other things ...

So I think at this point you will have to pick your own poison:)

Dale
On 03/22/2011 12:47 PM, Norbert Hartl wrote:

>
> Am 22.03.2011 um 19:56 schrieb [hidden email]
> <mailto:[hidden email]>:
>
>> Updates:
>> Status: Fixed
>>
>> Comment #1 on issue 254 by [hidden email]: DateAndTimes don't
>> compare correctly
>> http://code.google.com/p/glassdb/issues/detail?id=254
>>
>> If you look closley:
>>
>>
>> | date date2 |
>> date := DateAndTime now.
>> date2 := (DateAndTime fromString: (date printString)).
>> { date. date2. date = date2}
>>
>> results in:
>> anArray( 2011-03-22T11:49:51.581-07:00, 2011-03-22T11:49:51.581-07:00,
>> false)
>>
>> which tells us that the printStrings are the same, so the instances of
>> ScaledDecimal are equal (for all intents and purposes) ... but the
>> implementation of ScaledDecimal>>#= is ah, quirky and two
>> ScaledDecimals that print the same don't necessarily compare the same
>> and this behavior is "traditional" in that that's the way most
>> implementations work:)
>>
>> So in order to get ScaledDecimals to compare equal when they compare
>> equal, you have to round to your desired precision, so DateAndTime
>> class>>secondsSince2001 would look like this:
>>
>> secondsSince2001
>>
>> "^DateTime now asSecondsGmt - 3155760000."
>> ^ ((System _timeGmtFloat - 978307200) roundTo: 1/1000) asScaledDecimal: 3.
>>
>> Since this is the "expected" behavior for 2.0, there is no bug ... In
>> 3.0 the GemStone ScaledDecimals that print the same _will_ compare_ equal!
>
> Does this mean that the ScaledDecimal>>= is implemented differently. The
> effect is that if you create a ScaledDecimal it compiles to numerator
> and denominator. The equals check just compares those two values it will
> report false if they are different. So in my case there were different
> numerator and denominator that caculate to the same value at the given
> precision and therefor result in the same printString. I'm not sure if
> roundTo: will automatically lead to the same numerator and denominator
> in every case. Either I need this assurance or a better ScaledDecimal>=
> implementation.
>
> What do you think?
>
> Norbert

Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

NorbertHartl

Am 22.03.2011 um 21:22 schrieb Dale Henrichs:

> Norbert,
>
> I am not a mathematician, so I can't guarantee anything. I was under the impression that rounding by 1/1000 would result in an exact fraction for the ScaledDecimal which would imply that the same fraction would be used when the ScaledDecimal was created from a string ...
>
> Of course implementations hit corner cases. The only way to absolutely certain that the a DateAndTime created from a String will match the original DateAndTime is to use a String to create them both:
>
>  DateAndTime fromString: DateAndTime now asString
>
Or to use seconds for storage.

> We figured that the roundTo: would work, but I figured that a ScaledDecimal would work:) earlier.
>
Yes, me too. And I was astonished that I used the same thing for weeks until the problem showed up. It is not that easy to reproduce and that makes me kind of uncertain. As you are a developer I don't need to explain this :)

> As I mention in the email, you could use the printString in your comparison instead of #= and then there would be no need to round the ScaledDecimal ...
>
That is not possible. What I need is > comparison and that does not work with strings. Using a conversion to printString is not really feasible if used in the collection protocol.

> You could also change the implemention of fromString: to avoid ScaledDecimal, but I'm not sure that would solve your problem without having to fudge other things ...
>
If avoiding ScaledDecimal means to use SmallDouble I'm pretty confident it won't help :)

> So I think at this point you will have to pick your own poison:)
>
Let me phrase it like this: I hate it having to agree :)

thanks,

Norbert

> Dale
> On 03/22/2011 12:47 PM, Norbert Hartl wrote:
>>
>> Am 22.03.2011 um 19:56 schrieb [hidden email]
>> <mailto:[hidden email]>:
>>
>>> Updates:
>>> Status: Fixed
>>>
>>> Comment #1 on issue 254 by [hidden email]: DateAndTimes don't
>>> compare correctly
>>> http://code.google.com/p/glassdb/issues/detail?id=254
>>>
>>> If you look closley:
>>>
>>>
>>> | date date2 |
>>> date := DateAndTime now.
>>> date2 := (DateAndTime fromString: (date printString)).
>>> { date. date2. date = date2}
>>>
>>> results in:
>>> anArray( 2011-03-22T11:49:51.581-07:00, 2011-03-22T11:49:51.581-07:00,
>>> false)
>>>
>>> which tells us that the printStrings are the same, so the instances of
>>> ScaledDecimal are equal (for all intents and purposes) ... but the
>>> implementation of ScaledDecimal>>#= is ah, quirky and two
>>> ScaledDecimals that print the same don't necessarily compare the same
>>> and this behavior is "traditional" in that that's the way most
>>> implementations work:)
>>>
>>> So in order to get ScaledDecimals to compare equal when they compare
>>> equal, you have to round to your desired precision, so DateAndTime
>>> class>>secondsSince2001 would look like this:
>>>
>>> secondsSince2001
>>>
>>> "^DateTime now asSecondsGmt - 3155760000."
>>> ^ ((System _timeGmtFloat - 978307200) roundTo: 1/1000) asScaledDecimal: 3.
>>>
>>> Since this is the "expected" behavior for 2.0, there is no bug ... In
>>> 3.0 the GemStone ScaledDecimals that print the same _will_ compare_ equal!
>>
>> Does this mean that the ScaledDecimal>>= is implemented differently. The
>> effect is that if you create a ScaledDecimal it compiles to numerator
>> and denominator. The equals check just compares those two values it will
>> report false if they are different. So in my case there were different
>> numerator and denominator that caculate to the same value at the given
>> precision and therefor result in the same printString. I'm not sure if
>> roundTo: will automatically lead to the same numerator and denominator
>> in every case. Either I need this assurance or a better ScaledDecimal>=
>> implementation.
>>
>> What do you think?
>>
>> Norbert
>

Reply | Threaded
Open this post in threaded view
|

Re: Issue 254 in glassdb: DateAndTimes don't compare correctly

NorbertHartl
In reply to this post by Dale Henrichs

Am 22.03.2011 um 21:22 schrieb Dale Henrichs:

> So I think at this point you will have to pick your own poison:)

Well said. Testing creation of 100000 things gives in milliseconds

82       System _timeGmtFloat
2406    DateAndTime now (unaltered)
39806  DateAndTime now (with rounded and conversion to ScaledDecimal)

Norbert