I've found a rather strange behaviour with DateAndTime. In my code I have commands that have an executionTime. They do
execute executionTime := DateAndTime now. ... After that they are persisted. Today I recognized that the comparison between this DateAndTimes does not work as I would expect it. I'm not able to produce a test case because I don't know how to produce the circumstance. I can do in a workspace | date | date := DateAndTime now. date > (DateAndTime fromString: (date asString)) which prints to false. If I do the same with an object fetched from the storage | persistentDate | persistentDate := ..access persistent command... executionTime. persistentDate > (DateAndTime fromString: persistentDate asString) it evaluates to true. I think I know the reason but I can't recreate it in the workspace. DateAndTime now asSeconds class name resolves to SmallDouble while (DateAndTime fromString: (DateAndTime now asString)) asSeconds class name resolves to ScaledDecimal. While comparing the dates the ScaledDecimal is coerced to a SmallDouble and the value is slightly different. However I'm unable to produce anything from the workspace to reproduce the problem. Any hint is appreciated. And of course a way how to compare a DateAndTime object with a deserialized string version of a date. It was hard to see that comparison is based only on seconds anyway :) thanks, Norbert |
I think that I encountered the same thing before. I thought that Dale had fixed that. See the message thread "failing tests?"
Max On 21.03.2011, at 18:45, Norbert Hartl wrote: > I've found a rather strange behaviour with DateAndTime. In my code I have commands that have an executionTime. They do > > execute > executionTime := DateAndTime now. > ... > > After that they are persisted. Today I recognized that the comparison between this DateAndTimes does not work as I would expect it. I'm not able to produce a test case because I don't know how to produce the circumstance. I can do in a workspace > > | date | > date := DateAndTime now. > date > (DateAndTime fromString: (date asString)) > > which prints to false. If I do the same with an object fetched from the storage > > | persistentDate | > persistentDate := ..access persistent command... executionTime. > persistentDate > (DateAndTime fromString: persistentDate asString) > > it evaluates to true. I think I know the reason but I can't recreate it in the workspace. > > DateAndTime now asSeconds class name > > resolves to SmallDouble while > > (DateAndTime fromString: (DateAndTime now asString)) asSeconds class name > > resolves to ScaledDecimal. While comparing the dates the ScaledDecimal is coerced to a SmallDouble and the value is slightly different. However I'm unable to produce anything from the workspace to reproduce the problem. > > Any hint is appreciated. And of course a way how to compare a DateAndTime object with a deserialized string version of a date. It was hard to see that comparison is based only on seconds anyway :) > > thanks, > > Norbert |
Am 21.03.2011 um 19:01 schrieb Max Leske: > I think that I encountered the same thing before. I thought that Dale had fixed that. See the message thread "failing tests?" I did not find any references that looks like the problem I reported. Norbert > > > On 21.03.2011, at 18:45, Norbert Hartl wrote: > >> I've found a rather strange behaviour with DateAndTime. In my code I have commands that have an executionTime. They do >> >> execute >> executionTime := DateAndTime now. >> ... >> >> After that they are persisted. Today I recognized that the comparison between this DateAndTimes does not work as I would expect it. I'm not able to produce a test case because I don't know how to produce the circumstance. I can do in a workspace >> >> | date | >> date := DateAndTime now. >> date > (DateAndTime fromString: (date asString)) >> >> which prints to false. If I do the same with an object fetched from the storage >> >> | persistentDate | >> persistentDate := ..access persistent command... executionTime. >> persistentDate > (DateAndTime fromString: persistentDate asString) >> >> it evaluates to true. I think I know the reason but I can't recreate it in the workspace. >> >> DateAndTime now asSeconds class name >> >> resolves to SmallDouble while >> >> (DateAndTime fromString: (DateAndTime now asString)) asSeconds class name >> >> resolves to ScaledDecimal. While comparing the dates the ScaledDecimal is coerced to a SmallDouble and the value is slightly different. However I'm unable to produce anything from the workspace to reproduce the problem. >> >> Any hint is appreciated. And of course a way how to compare a DateAndTime object with a deserialized string version of a date. It was hard to see that comparison is based only on seconds anyway :) >> >> thanks, >> >> Norbert > |
I got a testfailure a while back for #testDateArithmetic: #testDateArithmetic The test fails when comparing two DateAndTime objects (same as your problem, right?). In my case there were two different primitives at work, one answered SmallDouble, the other SmallInt. I'm sorry if I should have put you on the wrong track. Just sounded very much like a similiar problem. Max On 21.03.2011, at 19:10, Norbert Hartl wrote:
|
Am 21.03.2011 um 19:58 schrieb Max Leske: Oh, I did not see this. I'm sorry. In fact it seems to be the same problem. I don't have a glue how to treat this, yet. And I'm not sure if fractions or floats/doubles are the perfect hit for representing time. Well, I'm sure there are not ;) Bad luck for me a scale of only seconds is too coarse grained for me. So get rid of DateAndTime and use millisecond rounded time might be best as intermediate Norbert
|
In reply to this post by NorbertHartl
Norbert and Max,
Max's problem had to do with comparing DateAndTime and Time and is covered in Issue 228[1], so Norbert's case is slightly different. Norbert, your problem is ultimately stemming from the fact that a Float cannot be accurately represented by it's printString. DateAndTime can use different classes to represent the number of seconds since the epoch. The default is to store seconds as a SmallDouble. When you create a DateAndTime from a String, the desire is to preserve the exact time specified in the String, so ScaledDecimal is used to represent the seconds. ScaledDecimal would be the choice to preserve equality across serialization steps. You _can_ change the precision used in DateAndTime by overriding DateAndTime class>>secondsSince2001 to return a ScaledDecimal with the number of digits of precision needed for your application (the SmallDouble gives you way more precision than you need)...then you will be able to exactly deserialize the DateAndTime. Dale [1] http://code.google.com/p/glassdb/issues/detail?id=228 On 03/21/2011 10:45 AM, Norbert Hartl wrote: > I've found a rather strange behaviour with DateAndTime. In my code I > have commands that have an executionTime. They do > > execute executionTime := DateAndTime now. ... > > After that they are persisted. Today I recognized that the comparison > between this DateAndTimes does not work as I would expect it. I'm not > able to produce a test case because I don't know how to produce the > circumstance. I can do in a workspace > > | date | date := DateAndTime now. date> (DateAndTime fromString: > (date asString)) > > which prints to false. If I do the same with an object fetched from > the storage > > | persistentDate | persistentDate := ..access persistent command... > executionTime. persistentDate> (DateAndTime fromString: > persistentDate asString) > > it evaluates to true. I think I know the reason but I can't recreate > it in the workspace. > > DateAndTime now asSeconds class name > > resolves to SmallDouble while > > (DateAndTime fromString: (DateAndTime now asString)) asSeconds class > name > > resolves to ScaledDecimal. While comparing the dates the > ScaledDecimal is coerced to a SmallDouble and the value is slightly > different. However I'm unable to produce anything from the workspace > to reproduce the problem. > > Any hint is appreciated. And of course a way how to compare a > DateAndTime object with a deserialized string version of a date. It > was hard to see that comparison is based only on seconds anyway :) > > thanks, > > Norbert |
Am 21.03.2011 um 20:41 schrieb Dale Henrichs: Agreed. Ok. It just made me wonder why this case occurrs so rare. With all my tests I couldn't produce a second case in the workspace. I could only test because I had a persisted example I could use over and over again. Thanks. I solved it. I don't like method overrides. They kill you sooner or later. I just added a method extension asDateAndTimeScaled: aNumber ^ DateAndTime secondsUTC: (seconds asScaledDecimal: aNumber) offset: nil So my code changes from executionTime := DateAndTime now. to executionTime := DateAndTime now asDateAndTimeScaled: self precisionScale It is neither pretty nor bad so I can live with it. Thanks again, Norbert
|
Norbert,
Yeah, I agree that overrides are nasty ... but they are necessary... in your case they aren't necessary, so that's good. Dale On 03/22/2011 08:45 AM, Norbert Hartl wrote: > > Am 21.03.2011 um 20:41 schrieb Dale Henrichs: > >> Norbert and Max, >> >> Max's problem had to do with comparing DateAndTime and Time and is >> covered in Issue 228[1], so Norbert's case is slightly different. >> >> Norbert, your problem is ultimately stemming from the fact that a Float >> cannot be accurately represented by it's printString. >> > Agreed. > >> DateAndTime can use different classes to represent the number of seconds >> since the epoch. The default is to store seconds as a SmallDouble. >> >> When you create a DateAndTime from a String, the desire is to preserve >> the exact time specified in the String, so ScaledDecimal is used to >> represent the seconds. ScaledDecimal would be the choice to preserve >> equality across serialization steps. >> > Ok. It just made me wonder why this case occurrs so rare. With all my > tests I couldn't produce a second case in the workspace. I could only > test because I had a persisted example I could use over and over again. > >> You _can_ change the precision used in DateAndTime by overriding >> DateAndTime class>>secondsSince2001 to return a ScaledDecimal with the >> number of digits of precision needed for your application (the >> SmallDouble gives you way more precision than you need)...then you >> will be able to exactly deserialize the DateAndTime. >> > Thanks. I solved it. I don't like method overrides. They kill you sooner > or later. I just added a method extension > > asDateAndTimeScaled: aNumber > ^ DateAndTime secondsUTC: (seconds asScaledDecimal: aNumber) offset: nil > > So my code changes from > > executionTime := DateAndTime now. > > to > > executionTime := DateAndTime now asDateAndTimeScaled: self precisionScale > > It is neither pretty nor bad so I can live with it. > > Thanks again, > > Norbert >> >> [1] http://code.google.com/p/glassdb/issues/detail?id=228 >> >> On 03/21/2011 10:45 AM, Norbert Hartl wrote: >>> I've found a rather strange behaviour with DateAndTime. In my code I >>> have commands that have an executionTime. They do >>> >>> execute executionTime := DateAndTime now. ... >>> >>> After that they are persisted. Today I recognized that the comparison >>> between this DateAndTimes does not work as I would expect it. I'm not >>> able to produce a test case because I don't know how to produce the >>> circumstance. I can do in a workspace >>> >>> | date | date := DateAndTime now. date> (DateAndTime fromString: >>> (date asString)) >>> >>> which prints to false. If I do the same with an object fetched from >>> the storage >>> >>> | persistentDate | persistentDate := ..access persistent command... >>> executionTime. persistentDate> (DateAndTime fromString: >>> persistentDate asString) >>> >>> it evaluates to true. I think I know the reason but I can't recreate >>> it in the workspace. >>> >>> DateAndTime now asSeconds class name >>> >>> resolves to SmallDouble while >>> >>> (DateAndTime fromString: (DateAndTime now asString)) asSeconds class >>> name >>> >>> resolves to ScaledDecimal. While comparing the dates the >>> ScaledDecimal is coerced to a SmallDouble and the value is slightly >>> different. However I'm unable to produce anything from the workspace >>> to reproduce the problem. >>> >>> Any hint is appreciated. And of course a way how to compare a >>> DateAndTime object with a deserialized string version of a date. It >>> was hard to see that comparison is based only on seconds anyway :) >>> >>> thanks, >>> >>> Norbert >> > |
In reply to this post by NorbertHartl
Dale,
the problem is not solved. I can produce DateAndTime objects which both carry a ScaledDecimal. But the numerator and denominator are somehow created differently so that the DateAndTimes are not equal. Although the string is equal while the objects are not. Scale is at 3 which is not a lot. Any ideas? Norbert Am 22.03.2011 um 16:45 schrieb Norbert Hartl:
|
Norbert,
Do you have examples that I can look at? Dale On 03/22/2011 10:07 AM, Norbert Hartl wrote: > Dale, > > the problem is not solved. I can produce DateAndTime objects which both > carry a ScaledDecimal. But the numerator and denominator are somehow > created differently so that the DateAndTimes are not equal. Although the > string is equal while the objects are not. Scale is at 3 which is not a lot. > > Any ideas? > > Norbert > > Am 22.03.2011 um 16:45 schrieb Norbert Hartl: > >> >> Am 21.03.2011 um 20:41 schrieb Dale Henrichs: >> >>> Norbert and Max, >>> >>> Max's problem had to do with comparing DateAndTime and Time and is >>> covered in Issue 228[1], so Norbert's case is slightly different. >>> >>> Norbert, your problem is ultimately stemming from the fact that a Float >>> cannot be accurately represented by it's printString. >>> >> Agreed. >> >>> DateAndTime can use different classes to represent the number of seconds >>> since the epoch. The default is to store seconds as a SmallDouble. >>> >>> When you create a DateAndTime from a String, the desire is to preserve >>> the exact time specified in the String, so ScaledDecimal is used to >>> represent the seconds. ScaledDecimal would be the choice to preserve >>> equality across serialization steps. >>> >> Ok. It just made me wonder why this case occurrs so rare. With all my >> tests I couldn't produce a second case in the workspace. I could only >> test because I had a persisted example I could use over and over again. >> >>> You _can_ change the precision used in DateAndTime by overriding >>> DateAndTime class>>secondsSince2001 to return a ScaledDecimal with >>> the number of digits of precision needed for your application (the >>> SmallDouble gives you way more precision than you need)...then you >>> will be able to exactly deserialize the DateAndTime. >>> >> Thanks. I solved it. I don't like method overrides. They kill you >> sooner or later. I just added a method extension >> >> asDateAndTimeScaled: aNumber >> ^ DateAndTime secondsUTC: (seconds asScaledDecimal: aNumber) offset: nil >> >> So my code changes from >> >> executionTime := DateAndTime now. >> >> to >> >> executionTime := DateAndTime now asDateAndTimeScaled: self precisionScale >> >> It is neither pretty nor bad so I can live with it. >> >> Thanks again, >> >> Norbert >>> >>> [1] http://code.google.com/p/glassdb/issues/detail?id=228 >>> >>> On 03/21/2011 10:45 AM, Norbert Hartl wrote: >>>> I've found a rather strange behaviour with DateAndTime. In my code I >>>> have commands that have an executionTime. They do >>>> >>>> execute executionTime := DateAndTime now. ... >>>> >>>> After that they are persisted. Today I recognized that the comparison >>>> between this DateAndTimes does not work as I would expect it. I'm not >>>> able to produce a test case because I don't know how to produce the >>>> circumstance. I can do in a workspace >>>> >>>> | date | date := DateAndTime now. date> (DateAndTime fromString: >>>> (date asString)) >>>> >>>> which prints to false. If I do the same with an object fetched from >>>> the storage >>>> >>>> | persistentDate | persistentDate := ..access persistent command... >>>> executionTime. persistentDate> (DateAndTime fromString: >>>> persistentDate asString) >>>> >>>> it evaluates to true. I think I know the reason but I can't recreate >>>> it in the workspace. >>>> >>>> DateAndTime now asSeconds class name >>>> >>>> resolves to SmallDouble while >>>> >>>> (DateAndTime fromString: (DateAndTime now asString)) asSeconds class >>>> name >>>> >>>> resolves to ScaledDecimal. While comparing the dates the >>>> ScaledDecimal is coerced to a SmallDouble and the value is slightly >>>> different. However I'm unable to produce anything from the workspace >>>> to reproduce the problem. >>>> >>>> Any hint is appreciated. And of course a way how to compare a >>>> DateAndTime object with a deserialized string version of a date. It >>>> was hard to see that comparison is based only on seconds anyway :) >>>> >>>> thanks, >>>> >>>> Norbert >>> >> > |
Dale,
I changed as you advized DateAndTime class>>secondsSince2001 "^DateTime now asSecondsGmt - 3155760000." ^ (System _timeGmtFloat - 978307200) asScaledDecimal: 3. If you then evaluate | date date2 | date := DateAndTime now. date2 := (DateAndTime fromString: (date printString)). date = date2 it resolves to false. Norbert Am 22.03.2011 um 18:17 schrieb Dale Henrichs: > Norbert, > > Do you have examples that I can look at? > > Dale > > On 03/22/2011 10:07 AM, Norbert Hartl wrote: >> Dale, >> >> the problem is not solved. I can produce DateAndTime objects which both >> carry a ScaledDecimal. But the numerator and denominator are somehow >> created differently so that the DateAndTimes are not equal. Although the >> string is equal while the objects are not. Scale is at 3 which is not a lot. >> >> Any ideas? >> >> Norbert >> >> Am 22.03.2011 um 16:45 schrieb Norbert Hartl: >> >>> >>> Am 21.03.2011 um 20:41 schrieb Dale Henrichs: >>> >>>> Norbert and Max, >>>> >>>> Max's problem had to do with comparing DateAndTime and Time and is >>>> covered in Issue 228[1], so Norbert's case is slightly different. >>>> >>>> Norbert, your problem is ultimately stemming from the fact that a Float >>>> cannot be accurately represented by it's printString. >>>> >>> Agreed. >>> >>>> DateAndTime can use different classes to represent the number of seconds >>>> since the epoch. The default is to store seconds as a SmallDouble. >>>> >>>> When you create a DateAndTime from a String, the desire is to preserve >>>> the exact time specified in the String, so ScaledDecimal is used to >>>> represent the seconds. ScaledDecimal would be the choice to preserve >>>> equality across serialization steps. >>>> >>> Ok. It just made me wonder why this case occurrs so rare. With all my >>> tests I couldn't produce a second case in the workspace. I could only >>> test because I had a persisted example I could use over and over again. >>> >>>> You _can_ change the precision used in DateAndTime by overriding >>>> DateAndTime class>>secondsSince2001 to return a ScaledDecimal with >>>> the number of digits of precision needed for your application (the >>>> SmallDouble gives you way more precision than you need)...then you >>>> will be able to exactly deserialize the DateAndTime. >>>> >>> Thanks. I solved it. I don't like method overrides. They kill you >>> sooner or later. I just added a method extension >>> >>> asDateAndTimeScaled: aNumber >>> ^ DateAndTime secondsUTC: (seconds asScaledDecimal: aNumber) offset: nil >>> >>> So my code changes from >>> >>> executionTime := DateAndTime now. >>> >>> to >>> >>> executionTime := DateAndTime now asDateAndTimeScaled: self precisionScale >>> >>> It is neither pretty nor bad so I can live with it. >>> >>> Thanks again, >>> >>> Norbert >>>> >>>> [1] http://code.google.com/p/glassdb/issues/detail?id=228 >>>> >>>> On 03/21/2011 10:45 AM, Norbert Hartl wrote: >>>>> I've found a rather strange behaviour with DateAndTime. In my code I >>>>> have commands that have an executionTime. They do >>>>> >>>>> execute executionTime := DateAndTime now. ... >>>>> >>>>> After that they are persisted. Today I recognized that the comparison >>>>> between this DateAndTimes does not work as I would expect it. I'm not >>>>> able to produce a test case because I don't know how to produce the >>>>> circumstance. I can do in a workspace >>>>> >>>>> | date | date := DateAndTime now. date> (DateAndTime fromString: >>>>> (date asString)) >>>>> >>>>> which prints to false. If I do the same with an object fetched from >>>>> the storage >>>>> >>>>> | persistentDate | persistentDate := ..access persistent command... >>>>> executionTime. persistentDate> (DateAndTime fromString: >>>>> persistentDate asString) >>>>> >>>>> it evaluates to true. I think I know the reason but I can't recreate >>>>> it in the workspace. >>>>> >>>>> DateAndTime now asSeconds class name >>>>> >>>>> resolves to SmallDouble while >>>>> >>>>> (DateAndTime fromString: (DateAndTime now asString)) asSeconds class >>>>> name >>>>> >>>>> resolves to ScaledDecimal. While comparing the dates the >>>>> ScaledDecimal is coerced to a SmallDouble and the value is slightly >>>>> different. However I'm unable to produce anything from the workspace >>>>> to reproduce the problem. >>>>> >>>>> Any hint is appreciated. And of course a way how to compare a >>>>> DateAndTime object with a deserialized string version of a date. It >>>>> was hard to see that comparison is based only on seconds anyway :) >>>>> >>>>> thanks, >>>>> >>>>> Norbert >>>> >>> >> > |
Free forum by Nabble | Edit this page |