Page 1 of 1

System.Date (v8.0)

Posted: Mon Oct 25, 2021 9:19 am
by gray
The new System.Date procedure in v8.0:

Code: Select all

PROCEDURE Date*;
  (* ... *)
  BEGIN
    (* ... *)
    IF S.class = Texts.Int THEN (*set clock*)
      (* ... *)
      IF (day >= 1) & (day <= 31) & (mo >= 1) & (mo <= 12) & (yr >= 0) & (yr <= 63) THEN
        dt := ((((yr*16 + mo)*32 + day)*32 + hr)*64 + min)*64 + sec;
        Kernel.SetClock(dt)
      END
    ELSE (*read clock*)
      dt := Oberon.Clock()
    END;
    Texts.WriteClock(W, dt); EndLine
  END Date;
can leave 'dt' undefined if one of the integer arguments has an out-of-range value. 'Texts.WriteClock(W, dt)' will then print a value that is most likely not correct.

I have fixed this thusly OMM:

Code: Select all

  PROCEDURE Date*;
  (* ... *)
  BEGIN
    (* ... *)
    IF S.class = Texts.Int THEN (*set clock*)
      (* ... *)
      IF (day >= 1) & (day <= 31) & (mo >= 1) & (mo <= 12) & (yr >= 0) & (yr <= 63) THEN
        dt := ((((yr*16 + mo)*32 + day)*32 + hr)*64 + min)*64 + sec;
        Kernel.SetClock(dt)
      END
    END;
    dt := Oberon.Clock();
    Texts.WriteClock(W, dt); EndLine
  END Date;
This has the additional advantage that we can verify that setting the clock via 'Kernel.SetClock' has worked.

Re: System.Date (v8.0)

Posted: Thu Oct 28, 2021 5:21 am
by gray
Checking for the correctness of the date and time actually set is also useful as we actually can set the clock even with incorrect parameters.

Here are two example cases with incorrect parameters where the clock gets set nonetheless. Typos happen. :(

Code: Select all

System.Date 28 10 n21 10 20 30
System.Date 28 10 21 10 20
Here's the variant I use that does a more thorough argument checking, also for the ranges of hours, mins, and secs.

Code: Select all

  PROCEDURE Date*;
    VAR
      S: Texts.Scanner;
      arg: ARRAY 6 OF LONGINT; (* day, month, year, hour, mins, secs *)
      dt, i: LONGINT;
  BEGIN
    Texts.WriteString(W, "System.Date"); EndLine;
    Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
    Texts.Scan(S); i := 0;
    WHILE (S.class = Texts.Int) & (i < 6) DO
      arg[i] := S.i; Texts.Scan(S); INC(i)
    END;
    IF i = 6 THEN
      IF (arg[0] >= 1) & (arg[0] <= 31) & (arg[1] >= 1) & (arg[1] <= 12) & (arg[2] >= 0) & (arg[2] <= 63)
        & (arg[3] >= 0) & (arg[3] <= 23) & (arg[4] >= 0) & (arg[4] <= 59) & (arg[5] >= 0) & (arg[5] <= 59) THEN
        dt := ((((arg[2]*16 + arg[1])*32 + arg[0])*32 + arg[3])*64 + arg[4])*64 + arg[5];
        Oberon.SetClock(dt)
      END
    END;
    dt := Oberon.Clock();
    Texts.WriteClock(W, dt); EndLine
  END Date;