"Exercise: ClockHour"

clockHour: hourInteger minute: minuteInteger
"Implement a clock that handles times without dates."
"(self new clockHour: 8 minute: 0) >>> '08:00'"
"(self new clockHour: 11 minute: 9) >>> '11:09'"
"(self new clockHour: -1 minute: 15) >>> '23:15'"
| totalMinutes hour minute |

    totalMinutes := (hourInteger * 60 + minuteInteger) \\ 1440.
    totalMinutes := totalMinutes negative
        ifTrue:  [ totalMinutes + 1440 ]
        ifFalse: [ totalMinutes ].

    hour   := totalMinutes // 60.
    minute := totalMinutes \\ 60.

    ^ '{1}{2}:{3}{4}' format: {
        (hour   < 10 ifTrue: ['0'] ifFalse: ['']).
        hour.
        (minute < 10 ifTrue: ['0'] ifFalse: ['']).
        minute }


"Tests"
testClock
"Create a new clock with an initial time - on the hour"
self assert: (task clockHour: 8 minute: 0) equals: '08:00'.
  "Create a new clock with an initial time - past the hour"
  self assert: (task clockHour: 11 minute: 9) equals: '11:09'.
  "Create a new clock with an initial time - midnight is zero hours"
  self assert: (task clockHour: 24 minute: 0) equals: '00:00'.
  "Create a new clock with an initial time - hour rolls over"
  self assert: (task clockHour: 25 minute: 0) equals: '01:00'.
  "Create a new clock with an initial time - hour rolls over continuously"
  self assert: (task clockHour: 100 minute: 0) equals: '04:00'.
  "Create a new clock with an initial time - sixty minutes is next hour"
  self assert: (task clockHour: 1 minute: 60) equals: '02:00'.
  "Create a new clock with an initial time - minutes roll over"
  self assert: (task clockHour: 0 minute: 160) equals: '02:40'.
  "Create a new clock with an initial time - minutes roll over continuously"
  self assert: (task clockHour: 0 minute: 1723) equals: '04:43'.
  "Create a new clock with an initial time - hour and minutes roll over"
  self assert: (task clockHour: 25 minute: 160) equals: '03:40'.
  "Create a new clock with an initial time - hour and minutes roll over continuously"
  self assert: (task clockHour: 201 minute: 3001) equals: '11:01'.
  "Create a new clock with an initial time - hour and minutes roll over to exactly midnight"
  self assert: (task clockHour: 72 minute: 8640) equals: '00:00'.
  "Create a new clock with an initial time - negative hour"
  self assert: (task clockHour: -1 minute: 15) equals: '23:15'.
  "Create a new clock with an initial time - negative hour rolls over"
  self assert: (task clockHour: -25 minute: 0) equals: '23:00'.
  "Create a new clock with an initial time - negative hour rolls over continuously"
  self assert: (task clockHour: -91 minute: 0) equals: '05:00'.
  "Create a new clock with an initial time - negative minutes"
  self assert: (task clockHour: 1 minute: -40) equals: '00:20'.
  "Create a new clock with an initial time - negative minutes roll over"
  self assert: (task clockHour: 1 minute: -160) equals: '22:20'.
  "Create a new clock with an initial time - negative minutes roll over continuously"
  self assert: (task clockHour: 1 minute: -4820) equals: '16:40'.
  "Create a new clock with an initial time - negative sixty minutes is previous hour"
  self assert: (task clockHour: 2 minute: -60) equals: '01:00'.
  "Create a new clock with an initial time - negative hour and minutes both roll over"
  self assert: (task clockHour: -25 minute: -160) equals: '20:20'.
  "Create a new clock with an initial time - negative hour and minutes both roll over continuously"
  self assert: (task clockHour: -121 minute: -5810) equals: '22:10'.

  self assert: (task clockHour: 6 minute: 41) equals: '06:41'.

  "Compare two clocks for equality - clocks with same time"
  self assert: (task clockHour: 15 minute: 37) equals: (task clockHour: 15 minute: 37).
  "Compare two clocks for equality - clocks a minute apart"
  self deny: (task clockHour: 15 minute: 36) equals: (task clockHour: 15 minute: 37).
  "Compare two clocks for equality - clocks an hour apart"
  self deny: (task clockHour: 14 minute: 37) equals: (task clockHour: 15 minute: 37).
  "Compare two clocks for equality - clocks with hour overflow"
  self assert: (task clockHour: 10 minute: 37) equals: (task clockHour: 34 minute: 37).
  "Compare two clocks for equality - clocks with hour overflow by several days"
  self assert: (task clockHour: 3 minute: 11) equals: (task clockHour: 99 minute: 11).
  "Compare two clocks for equality - clocks with negative hour"
  self assert: (task clockHour: 22 minute: 40) equals: (task clockHour: -2 minute: 40).
  "Compare two clocks for equality - clocks with negative hour that wraps"
  self assert: (task clockHour: 17 minute: 3) equals: (task clockHour: -31 minute: 3).
  "Compare two clocks for equality - clocks with negative hour that wraps multiple times"
  self assert: (task clockHour: 13 minute: 49) equals: (task clockHour: -83 minute: 49).
  "Compare two clocks for equality - clocks with minute overflow"
  self assert: (task clockHour: 0 minute: 1) equals: (task clockHour: 0 minute: 1441).
  "Compare two clocks for equality - clocks with minute overflow by several days"
  self assert: (task clockHour: 2 minute: 2) equals: (task clockHour: 2 minute: 4322).
  "Compare two clocks for equality - clocks with negative minute"
  self assert: (task clockHour: 2 minute: 40) equals: (task clockHour: 3 minute: -20).
  "Compare two clocks for equality - clocks with negative minute that wraps"
  self assert: (task clockHour: 4 minute: 10) equals: (task clockHour: 5 minute: -1490).
  "Compare two clocks for equality - clocks with negative minute that wraps multiple times"
  self assert: (task clockHour: 6 minute: 15) equals: (task clockHour: 6 minute: -4305).
  "Compare two clocks for equality - clocks with negative hours and minutes"
  self assert: (task clockHour: 7 minute: 32) equals: (task clockHour: -12 minute: -268).
  "Compare two clocks for equality - clocks with negative hours and minutes that wrap"
  self assert: (task clockHour: 18 minute: 7) equals: (task clockHour: -54 minute: -11513).
  "Compare two clocks for equality - full clock and zeroed clock"
  self assert: (task clockHour: 24 minute: 0) equals: (task clockHour: 0 minute: 0).