-- file: TimeExtraImpl.mesa, last edit:
-- Bruce, March 16, 1979  6:10 PM
-- HGM, January 27, 1981  5:35 PM

-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  String USING [
    InvalidNumber, StringBoundsFault, StringToNumber, AppendChar,
    EquivalentSubString, UpperCase, SubStringDescriptor],
  System USING [gmtEpoch],
  Time USING [Pack, Packed, Unpacked, Invalid],
  TimeExtra USING [];

TimeExtraImpl: PROGRAM IMPORTS String, Time EXPORTS TimeExtra =
  BEGIN

  Empty: PROCEDURE [s: STRING] RETURNS [BOOLEAN] =
    BEGIN RETURN[s = NIL OR s.length = 0] END;

  EquivalentChar: PUBLIC PROCEDURE [c1, c2: CHARACTER] RETURNS [BOOLEAN] =
    BEGIN RETURN[String.UpperCase[c1] = String.UpperCase[c2]] END;

  GetToken: PROCEDURE [storage: STRING, s: STRING, c: CARDINAL]
    RETURNS [is: CARDINAL] =
    BEGIN
    ch: CHARACTER;
    FOR is ← c, is + 1 UNTIL is >= s.length DO
      SELECT String.UpperCase[ch ← s[is]] FROM
	IN ['A..'Z], IN ['0..'9] => String.AppendChar[storage, ch];
	':, '- => EXIT; -- terminator

	'  => IF ~Empty[storage] THEN EXIT; --terminating blank

	ENDCASE;
      ENDLOOP;
    RETURN[is + 1];
    END;

  PackedTimeFromString: PUBLIC PROCEDURE [s: STRING] RETURNS [t: Time.Packed] =
    BEGIN
    --  string format must be: bDD-MMM-YYbbHH:MM:SSbbZZTb
    t ← DoIt[
      s !
      String.InvalidNumber, String.StringBoundsFault, Time.Invalid =>
	BEGIN t ← System.gmtEpoch; CONTINUE END]
    END;

  DoIt: PROCEDURE [s: STRING] RETURNS [t: Time.Packed] =
    BEGIN

    Get: PROCEDURE =
      BEGIN s1.length ← 0; nextChar ← GetToken[s1, s, nextChar] END;

    GetNumber: PROCEDURE RETURNS [CARDINAL] =
      BEGIN Get[]; RETURN[String.StringToNumber[s1, 10]]; END;

    m: String.SubStringDescriptor ←
      [base: "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"L, offset: NULL, length: 3];
    s1: STRING ← [3];
    month: String.SubStringDescriptor ← [base: s1, offset: 0, length: NULL];
    time: Time.Unpacked ← [0, 0, 0, 0, 0, 0, 0, 8, FALSE];
    nextChar: CARDINAL ← 0;
    i: CARDINAL;
    packIt: BOOLEAN ← TRUE;



    IF Empty[s] THEN RETURN[System.gmtEpoch];
    time.day ← GetNumber[];
    Get[];
    month.length ← s1.length;
    FOR i IN [0..12) DO
      m.offset ← i*3;
      IF String.EquivalentSubString[@month, @m] THEN
	BEGIN time.month ← i; EXIT END;
      ENDLOOP;
    time.year ← GetNumber[];
    time.year ← time.year + 1900;
    time.hour ← GetNumber[];
    time.minute ← GetNumber[];
    time.second ← GetNumber[];
    Get[];
    IF s1.length # 0 THEN
      BEGIN
      zones: PACKED ARRAY [5..8] OF CHARACTER = ['E, 'C, 'M, 'P];
      FOR i IN [5..8] DO
	IF EquivalentChar[s1[0], zones[i]] THEN BEGIN time.zone ← i; EXIT END;
	REPEAT FINISHED => time.zone ← 0; -- GMT

	ENDLOOP;
      time.dst ← EquivalentChar[s1[1], 'D];
      packIt ← FALSE;
      END;
    t ← Time.Pack[time, packIt]
    END;

  END.