The Night Shift Bug
The parcel depot runs at night: it opens at 22:00 and closes at 06:00 the next morning. The first "are we open?" check was copied from a daytime shop, so it insists that 01:00 is outside a 22:00–06:00 window and that the night shift is minus sixteen hours long. Your job is three small procedures that get windows crossing midnight right — and that refuse the undefined time 0T with a clear message instead of a runtime crash.
Requirements
Create a codeunit named "Depot Hours" with three public procedures:
procedure IsOpen(At: Time; OpensAt: Time; ClosesAt: Time): Boolean
procedure ShiftMinutes(StartTime: Time; EndTime: Time): Integer
procedure MinutesUntilClose(At: Time; OpensAt: Time; ClosesAt: Time): IntegerRules:
- An opening window runs from
OpensAttoClosesAt. WhenClosesAtis later on the clock thanOpensAtit is a daytime window (08:00–17:00). WhenClosesAtis earlier on the clock thanOpensAtthe window crosses midnight: 22:00–06:00 covers 22:00 up to midnight and midnight up to 06:00. IsOpenreturnstruewhenAtlies inside the window. The opening instant is open and the closing instant is closed: for 22:00–06:00, 22:00 exactly is open, 23:30 and 01:00 are open, 06:00 exactly is closed, 07:00 is closed.- When
OpensAtequalsClosesAtthe depot is open round the clock:IsOpenreturnstruefor everyAt, includingAtequal to that shared time. ShiftMinutesreturns the length of a shift in whole minutes fromStartTimetoEndTime, wrapping past midnight whenEndTimeis earlier on the clock: 22:00 to 06:00 is 480, 08:00 to 16:30 is 510, 23:59 to 00:01 is 2. Leftover seconds are dropped, never rounded up: 08:15:15 to 09:00:00 is 44. A shift whoseEndTimeequals itsStartTimeis 0 minutes long — a shift is a duration, so equal times mean nothing happened, unlike the round-the-clock rule for a window.MinutesUntilClosereturns 0 when the depot is closed atAt(rule 2 decides, so exactly atClosesAtit is 0). Otherwise it returns the whole minutes fromAtuntil the clock next readsClosesAt, counting past midnight when needed: for 22:00–06:00, 23:30 gives 390 and 01:00 gives 300. "Next" means strictly in the future, so in a round-the-clock windowAtequal toClosesAtgives a full 1440.0Tis the undefined time: adding to it or subtracting it is a runtime error, and the runtime's own message is not what a user should see. Every procedure must check itsTimeparameters first and, when any of them is0T, callErrorwith a message that contains the textundefined time (0T)— for exampleStartTime is an undefined time (0T).
What you need from AL: Time values compare with the ordinary <, >= and = operators; Time - Time gives the difference in milliseconds as an Integer, negative when the left value is earlier on the clock; Time + Integer moves a time forward by that many milliseconds; div divides two integers and throws the remainder away. A minute is 60 × 1000 milliseconds and a day is 24 × 60 × 60 × 1000.
Pick object IDs in the 50100–50199 range and reference other objects by name, never by ID.
What the tests check
The IsOpen tests use the 22:00–06:00 window at 22:00, 23:30, 01:00, 06:00 and 07:00, an 08:00–17:00 window at exactly 08:00 (open), at a generated minute inside it, at exactly 17:00 (closed) and at 06:00 and 19:00 outside it, and two round-the-clock windows: 00:00–00:00 at a generated minute and 06:00–06:00 at exactly 06:00. ShiftMinutes is checked with a generated daytime length (08:00 plus 1–600 minutes), 22:00–06:00 (480), 23:59–00:01 (2), a generated time paired with itself (0) and 08:15:15–09:00:00 (44 — seconds dropped, not rounded). MinutesUntilClose expects 390 at 23:30 and 300 at 01:00 for 22:00–06:00, 0 at 06:00 and at 07:00, the exact remaining minutes at a generated minute inside 08:00–17:00 and 0 at exactly 17:00, 180 at 21:00 in a 00:00–00:00 window and 1440 at 06:00 in a 06:00–06:00 window. Finally, every Time parameter of every procedure is tried with 0T in turn (At, OpensAt and ClosesAt for IsOpen and MinutesUntilClose; StartTime and EndTime for ShiftMinutes), with the other arguments defined, and each call must fail with an error message that contains undefined time (0T) — the test shows the actual error text when it does not match.
Learn More
- Time data type — the
hhmmssTliteral syntax and what0Tmeans. - Arithmetic operators — the type table that says
Time - Timeis anIntegerof milliseconds,Time + Integeris aTime, and that0Tis a runtime error. - AL operators —
div,modand the comparison operators, with their precedence. - Dialog.Error(Text [, Any,...]) method — raising your own error with a placeholder for the parameter name.