-- File: Dates.mesa last edit by: -- Smokey on: Dec 2, 1980 4:20 PM -- Mark on: Apr 19, 1979 10:27 AM -- Karlton on: Nov 11, 1980 11:03 AM DIRECTORY Date USING [Packed], Storage USING [EmptyString, String], String USING [ AppendChar, EqualString, EquivalentString, StringBoundsFault, StringToNumber, UpperCase], System USING [gmtEpoch], Time USING [Append, Current, Invalid, Pack, Unpack, Unpacked]; Dates: PROGRAM IMPORTS Storage, String, Time EXPORTS Date = BEGIN -- types BufferObject: TYPE = RECORD [ p: CARDINAL, s: STRING]; Buffer: TYPE = POINTER TO BufferObject; -- exported procedures StringToPacked: PUBLIC PROCEDURE [s: STRING] RETURNS[tod: Date.Packed] = BEGIN buffer: BufferObject ← [0, s]; RETURN[ IF Storage.EmptyString[s] OR String.EquivalentString[s, " 5-Feb-37 22:28:15"L] THEN System.gmtEpoch ELSE GetDate[@buffer]] END; PackedToString: PUBLIC PROCEDURE [pt: Date.Packed] RETURNS[STRING] = BEGIN s: STRING ← NIL; IF pt = LAST[LONG CARDINAL] THEN RETURN[s]; s ← Storage.String[20]; Time.Append[s, Time.Unpack[pt]]; RETURN[s] END; -- local procedures GetDate: PROCEDURE [b: Buffer] RETURNS [Date.Packed] = BEGIN token: STRING ← [20]; monthFound, thisIsMonth: BOOLEAN ← FALSE; index: CARDINAL[0..12); ambig1, ambig2: CARDINAL ← 0; number: CARDINAL; u: Time.Unpacked ← [0,0,0,0,0,0,0,0,FALSE]; now: Time.Unpacked ← Time.Unpack[Time.Current[]]; DO NextItem[b,token]; IF token.length = 0 THEN EXIT; [thisIsMonth, index] ← IsMonth[token]; IF thisIsMonth THEN BEGIN u.month ← index; monthFound ← TRUE; LOOP END; IF IsNumber[token] THEN BEGIN IF u.year > 0 THEN BEGIN -- working on the time of day number ← String.StringToNumber[token, 10]; u.hour ← number; NextItem[b,token]; IF IsNumber[token] THEN -- :s get tossed by NextItem routine u.minute ← String.StringToNumber[token, 10]; NextItem[b,token]; IF IsNumber[token] THEN BEGIN u.second ← String.StringToNumber[token, 10]; NextItem[b,token]; END; IF String.EqualString[token,"PM"L] AND u.hour < 12 THEN u.hour ← u.hour+12; END ELSE BEGIN number ← String.StringToNumber[token, 10]; IF number > 32 THEN u.year ← number ELSE IF number > 12 THEN u.day ← number ELSE IF ambig1 = 0 THEN ambig1 ← number ELSE ambig2 ← number; END; END; ENDLOOP; IF ambig2 > 0 THEN BEGIN u.month ← ambig1 - 1; u.day ← ambig2; monthFound ← TRUE; END ELSE IF ambig1 > 0 THEN IF u.day = 0 THEN u.day ← ambig1 ELSE IF u.month = 0 AND ~monthFound THEN BEGIN u.month ← ambig1 - 1; monthFound ← TRUE; END; IF u.day = 0 THEN u.day ← now.day; IF ~monthFound THEN u.month ← now.month; IF u.year = 0 THEN u.year ← now.year; IF u.year < 37 THEN u.year ← u.year + 2000 ELSE IF u.year < 100 THEN u.year ← u.year + 1900; RETURN[Time.Pack[u, TRUE]] END; IsMonth: PROCEDURE [candidate: STRING] RETURNS [BOOLEAN, CARDINAL] = BEGIN Months: ARRAY [0..12) OF STRING = [ "JANUARY"L,"FEBRUARY"L,"MARCH"L,"APRIL"L,"MAY"L,"JUNE"L,"JULY"L, "AUGUST"L,"SEPTEMBER"L,"OCTOBER"L,"NOVEMBER"L,"DECEMBER"L]; i,j: CARDINAL; test: STRING; IF candidate.length = 0 THEN RETURN[FALSE, 0]; IF candidate[0] NOT IN ['A..'Z] THEN RETURN[FALSE, 0]; IF candidate.length >= 3 THEN FOR i IN [0..12) DO test ← Months[i]; IF candidate.length <= test.length THEN FOR j IN [0..candidate.length) DO IF candidate[j] # test[j] THEN EXIT; REPEAT FINISHED => RETURN[TRUE, i]; ENDLOOP; ENDLOOP; ERROR Time.Invalid; END; IsNumber: PROCEDURE [s: STRING] RETURNS [BOOLEAN] = BEGIN i: CARDINAL; IF s.length = 0 THEN RETURN[FALSE]; FOR i IN [0..s.length) DO IF s[i] NOT IN ['0..'9] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] END; NextItem: PROCEDURE [b: Buffer, token: STRING] = BEGIN OPEN String; c: CHARACTER; alpha, number: BOOLEAN ← FALSE; token.length ← 0; WHILE b.p < b.s.length DO c ← b.s[b.p]; b.p ← b.p+1; SELECT c FROM IN ['a..'z], IN ['A..'Z] => BEGIN IF number THEN BEGIN b.p ← b.p-1; EXIT END; AppendChar[token, UpperCase[c] ! String.StringBoundsFault => CONTINUE]; alpha ← TRUE; END; IN ['0..'9] => BEGIN IF alpha THEN BEGIN b.p ← b.p-1; EXIT END; AppendChar[token, c ! String.StringBoundsFault => CONTINUE]; number ← TRUE; END; ENDCASE => IF token.length # 0 THEN EXIT; ENDLOOP; RETURN END; END. -- Date.mesa