<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Thu, Oct 18, 2018 at 10:27 AM Bert Freudenberg <<a href="mailto:bert@freudenbergs.de">bert@freudenbergs.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">I'm not sure this is right.</div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"><br></div><div><font color="#000000" face="arial, helvetica, sans-serif">The current implementation comes from the "trunk thinks its tomorrow" discussion starting on 17 Feb 2016. As a result we introduced the "noTimezone" notion: a date without timezone compares equal to the same date in any time zone. At some point this made all the tests green.</font></div></div></div></blockquote><div>True. But we were missing some tests (we should have a test the check everywhere we defined #= to validate that equal objects also have equal #hash).</div><div>As a consequence of that change, the following also happens:</div><div>   dates := { Date today.  DateAndTime now asDate }.</div><div><div>   dates first = dates second. "=true"</div><div>   dates asSet size. "=2"</div></div><div>Also, using dates as keys in Dictionaries might not work correctly, either.</div><div><br></div><div>We could fix these issues by altering #hash so that equal dates hash equally - say, hashing ticks and maybe duration:</div><div>hash</div><div>   | ticks |</div><div>   ticks := start ticks.</div><div>   ^((ticks second // 86400 + ticks first) hashMultiply bitXor: ticks second \\ 86400 bitXor: ticks third)</div><div>      + duration hash</div><div> but explicitly ignoring offset.  This would "work" such that any date with the same starting time (ignoring offset) would have the same hash.  The Set example above would resolve down to 1, but dates with different offsets would still be present in the Set (since that relies on #=, which would be different in this case).</div><div><br></div><div>However, if we used Dates as a key in Dictionary, then the different Dates with offsets will work fine, but the Date without offset will map to the first date key in the chain for the same hash key, but not the others.  This invokes weird behaviour like:</div><div><div>  |dict|</div><div>  dict := Dictionary new: 3.</div><div>  dict </div><div><span style="white-space:pre">   </span>at: (DateAndTime now offset: 3 hours) asDate put: '3 hours';</div><div><span style="white-space:pre">  </span>at: (DateAndTime now offset: -6 hours) asDate put: '-6 hours'.</div><div>  dict at: Date today. "=> '3 hours' "</div><div>  dict removeKey: (DateAndTime now offset: 3 hours) asDate.</div><div>  dict at: Date today. "=> '-6 hours' "</div></div><div><br></div><div>Not ideal.  (Of course, this is how Dates behave for us today as well.  Even weirder if you put the Date today in as a key first - unpredictable results ensue.)</div><div><br></div><div>That's why I like this change - I can't think of a better one.  Except maybe having 2 Date classes like Richard is suggesting.</div><div><br></div><div>-cbc</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)"><br></div><div style="font-family:arial,helvetica,sans-serif;font-size:small;color:rgb(0,0,0)">- Bert -</div><div><div dir="ltr" class="gmail-m_-2668565978295285731gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div dir="ltr"> </div></div></div></div></div></div></div><div class="gmail_quote"><div dir="ltr">On Wed, Oct 17, 2018 at 8:53 PM Chris Cunningham <<a href="mailto:cunningham.cb@gmail.com" target="_blank">cunningham.cb@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">I like this.<div><br></div><div>Although I notice that the comparison makes sure that the classes are the same - so a Timespan starting at the exact same time as a Date and with 24 hour duration is not the same as a Date with the exact same values.</div><div><br></div><div>This would allow further speedups if Date, Week, Month, and Year if we wanted - just drop the comparison of duration in those classes.  (The general case is still needed to tell Timespan apart from Schedule.)</div><div><br></div><div>If you did that, you probably also want to re-implement hash as well - simplifying it the same way.</div><div><br></div><div>-cbc</div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, Oct 17, 2018 at 8:07 PM <<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Chris Muller uploaded a new version of Chronology-Core to project The Inbox:<br>
<a href="http://source.squeak.org/inbox/Chronology-Core-cmm.14.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/inbox/Chronology-Core-cmm.14.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Chronology-Core-cmm.14<br>
Author: cmm<br>
Time: 17 October 2018, 10:07:14.485014 pm<br>
UUID: 5d93900c-4a4e-4a4e-80f3-800dbdb07d0b<br>
Ancestors: Chronology-Core-tcj.12<br>
<br>
- A fix and optimization of Timespan>>#=.  Both elements being compared must have the same timezone (or same state of #noTimezone) in order to take advantage of the optimized #hasEqualTicks: comparison.  Otherwise (if different timezones), a full comparison of their starts (via #=) is needed.<br>
- There was a mention of this optimization put into the class comment.  This level of detail may be a bit tedious for users to read at that level, so Brents original comment was restored.<br>
<br>
=============== Diff against Chronology-Core-tcj.12 ===============<br>
<br>
Item was changed:<br>
  Magnitude subclass: #Timespan<br>
        instanceVariableNames: 'start duration'<br>
        classVariableNames: ''<br>
        poolDictionaries: ''<br>
        category: 'Chronology-Core'!<br>
<br>
+ !Timespan commentStamp: 'cmm 10/17/2018 22:00' prior: 0!<br>
+ I represent a duration starting on a specific DateAndTime.!<br>
- !Timespan commentStamp: 'bf 2/18/2016 14:43' prior: 0!<br>
- I represent a duration starting on a specific DateAndTime.<br>
- <br>
- If my start has an offset identical to my #defaultOffset then comparisons ignore timezone offset.!<br>
<br>
Item was changed:<br>
  ----- Method: Timespan>>= (in category 'ansi protocol') -----<br>
  = comparand<br>
+     ^ self class = comparand class <br>
+         and: [(((self noTimezone and: [comparand noTimezone]) or: [self start offset = comparand start offset])<br>
+             ifTrue: [ self start hasEqualTicks: comparand start ]<br>
+             ifFalse: [ self start = comparand start ])<br>
+         and: [ self duration = comparand duration ] ]<br>
-       ^ self class = comparand class <br>
-               and: [((self noTimezone or: [ comparand noTimezone ])<br>
-                       ifTrue: [ self start hasEqualTicks: comparand start ]<br>
-                       ifFalse: [ self start = comparand start ])<br>
-               and: [ self duration = comparand duration ] ]<br>
  .!<br>
<br>
<br>
</blockquote></div>
<br>
</blockquote></div></div></div>
<br>
</blockquote></div></div></div></div></div></div>