/* rexx */ /*-------------------------------------------------------------------*/ /* */ /* REXX Exec : ISDATE */ /* */ /* Description : Checks a passed string to see if it is a valid */ /* date or not. */ /* */ /* Created on : 15 Oct 2018 */ /* Created by : Kevin Ferguson */ /* : Userid MIT001 */ /* : Using ABBYDALE.DEVL.REXX(ISDATE) */ /* */ /* Called by : */ /* */ /* Calls : CountStr */ /* */ /* Panels Used : None */ /* */ /* Return Codes : 0 - Date is valid */ /* 4 - Help displayed */ /* 8 - Date is invalid */ /* 12 - Incorrect date format */ /* */ /* Change Activity : */ /* */ /* MM/DD/YYYY ID Comment */ /* --------------------------------------------------------------- */ /* 05/15/2019 DSF Changed to allow for dates in the local date */ /* format (dd mmm yyyy) i.e 5 May 2019 */ /* */ /* ©Copyright of Abbydale Systems LLC. */ /* */ /*-------------------------------------------------------------------*/ Parse upper Arg Help DateForm /* Check for Help */ testdate = ARG(1) Dateform = ARG(2) signal on halt /* attention key */ upper testdate upper dateform mon.1 = 31 /* Days in January */ mon.2 = 28 /* Days in February */ mon.3 = 31 /* Days in March */ mon.4 = 30 /* Days in April */ mon.5 = 31 /* Days in May */ mon.6 = 30 /* Days in June */ mon.7 = 31 /* Days in July */ mon.8 = 31 /* Days in August */ mon.9 = 30 /* Days in September */ mon.10 = 31 /* Days in October */ mon.11 = 30 /* Days in November */ mon.12 = 31 /* Days in December */ daysfirst = "N" mnn.1 = 'January' /* January DSF */ mnn.2 = 'February' /* February DSF */ mnn.3 = 'March' /* March DSF */ mnn.4 = 'April' /* April DSF */ mnn.5 = 'May' /* May DSF */ mnn.6 = 'June' /* June DSF */ mnn.7 = 'July' /* July DSF */ mnn.8 = 'August' /* August DSF */ mnn.9 = 'September' /* September DSF */ mnn.10 = 'October' /* October DSF */ mnn.11 = 'November' /* November DSF */ mnn.12 = 'December' /* December DSF */ daysfirst = "N" If Help = "?" Then do Call Disp_Help exit(4) end term = 8 type = 2 if length(Dateform) <> 0 then do term = 12 if DATATYPE(DateForm,U) = 0 then exit(term) if length(DateForm) <> 8 then exit(term) select WHEN DateForm = "DDMMYYYY" then do type = 1 end WHEN DateForm = "MMDDYYYY" then do type = 2 end WHEN DateForm = "YYYYMMDD" then do type = 3 end WHEN DateForm = "YYYYDDMM" then do type = 4 end otherwise exit(term) end end term = 8 /* Set bad date return code */ testdate = strip(testdate,b,'"') testdate = strip(testdate,b,"'") if POS('/',testdate) = 0 then do /*DSF*/ if words(testdate) <> 3 then exit(term) /*DSF*/ if length(word(testdate,2)) <> 3 then exit(term) /*DSF*/ if length(word(testdate,3)) <> 4 then exit(term) /*DSF*/ if datatype(word(testdate,3),n) <> 1 then exit(term) /*DSF*/ if datatype(word(testdate,1),n) <> 1 then exit(term) /*DSF*/ if datatype(word(testdate,2),m) <> 1 then exit(term) /*DSF*/ month = "DSF" /*DSF*/ testmon = translate(word(testdate,2)) /*DSF*/ Do I = 1 to 12 /*DSF*/ testi = translate(mnn.i) /*DSF*/ If testmon = LEFT(testi,3) then do /*DSF*/ month = i /*DSF*/ I = 12 /*DSF*/ end /*DSF*/ end /*DSF*/ if month = "DSF" then exit(term) /*DSF*/ testdate = word(testdate,1)"/"month"/"word(testdate,3) /*DSF*/ type = 1 /*DSF*/ end /*DSF*/ if length(testdate) > 10 then exit(term) if length(testdate) < 8 then exit(term) /* We now know the date length is good(ish) 8 < testdate < 10 */ dimindx = 1 /* Point at start of string */ stringtest = testdate /* Point at end of string */ chunks = 0 /* Count of seperators */ if countstr('/',stringtest) <> 2 then exit(term) gauge = 2 /* Moving start */ do i = 1 to 3 if pos('/',stringtest) > 0 then do gauge = pos('/',stringtest) dim.dimindx = SUBSTR(stringtest,1,gauge-1) if DATATYPE(Dim.dimindx,N) = 0 then exit(term) kf = length(stringtest)-(Pos('/',stringtest)) stringtest = substr(stringtest,gauge+1, kf) dimindx = dimindx + 1 end else do dim.dimindx = stringtest end end /* Do loop end */ select WHEN type = 1 then do day = dim.1 month = dim.2 year = dim.3 end WHEN type = 2 then do day = dim.2 month = dim.1 year = dim.3 end WHEN type = 3 then do day = dim.3 month = dim.2 year = dim.1 end WHEN type = 4 then do day = dim.2 month = dim.3 year = dim.1 end otherwise exit(term) end /* At this point we have all we need to check the validity */ If year < 1753 then exit(term) /* No dates less that 1753 */ If month > 12 then exit(term) /* no month higher than 12 */ month = month + 0 /* This drop the leading 0 */ leap = year//4 if leap = 0 then do mon.2 = "29" if year//100 = 0 then do mon.2 = "28" if year//400 = 0 then mon.2 = "29" end else do if year//400 = 0 then do mon.2 = "29" end end end If day > mon.month then exit(term) /* check days in month */ term = 0 exit(term) /*-------------------------------------------------------------------*/ /* Disp_Help Procedure */ /*-------------------------------------------------------------------*/ Disp_Help: Procedure say "ISDATE - Will validate a date passed to it." say"" say "Usage: ISDATE (testdate, dateform) | ?" say"" say" testdate - Is the date to be checked. It should have /s" say" to deliniate the day, month and year. The format" say" can be controlled by the optional dateformat" say" parameter." say"" say" dateform - (optional) defines the input format for the date" say" minus the /s ie. DDMMYYYY. The default is mMDDYYYY" say"" say" ? - Generates this information." say"" say" Return Codes :" say" 0 - Passed date is a valid" say" 4 - Help displayed" say" 8 - Passed date is invalid" say" 12 - Invalid format for date format" say"" Return /*-------------------------------------------------------------------*/ /* End of Disp_Help Procedure */ /*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/ /* Trap HALT Condition */ /*-------------------------------------------------------------------*/ halt: say "HALT acknowledged in line" sigl say "Cleanup processing in progress" address "TSO" "delstack" exit(16) /*-------------------------------------------------------------------*/ /* End of ISDATE */ /*-------------------------------------------------------------------*/