Search code examples
clips

CLIPS compare 2 dates


I'm trying to compare 2 dates to see if one person is older than 25 years old. I tried to bind a variable to the subtraction of the current date and his birthday, and then compare the variable to 25:

(deftemplate data
  (multislot current_date (type INTEGER))
)
(deffacts today
      (data (current_date 12 4 2018))
    )
(deftemplate driver
  (multislot name)
  (multislot dateBorn)
)

(deffacts drivers
  (driver (name Daniel Silva)(dateBorn 3 4 1985))
  (driver (name Carlos Santos)(dateBorn 3 4 2000))
)

(defrule cantDrive
  (driver(dateBorn $? ?age))
  (data (current_date $? ?date))
  (bind ?data (- ?age ?date))
  (test(< ?data 25))
  =>
  (printout t "He is younger than 25" crlf)
)

The above code doesn’t run, and I don’t understand why. Is there any operation that is incorrect? Is there any way to compare two dates? For example, I was born in 26/06/1997 and if I need to be at least 25 to rent a car, how do I confirm that? I can set the current date.


Solution

  •          CLIPS (6.31 2/3/18)
    CLIPS> 
    (deffunction current-date ()
       (bind ?lt (local-time))
       (format nil "%04d-%02d-%02d" (nth$ 1 ?lt) (nth$ 2 ?lt) (nth$ 3 ?lt)))
    CLIPS>    
    (deffunction is-leap-year (?year)
       (if (= (mod ?year 400) 0) then (return TRUE))
       (if (= (mod ?year 100) 0) then (return FALSE))
       (if (= (mod ?year 4) 0) then (return TRUE))
       (return FALSE))
    CLIPS> 
    (defglobal ?*days-before-month* =           (create$ 0 31 59 90 120 151 181 212 243 273 304 334))
    CLIPS> (defglobal ?*days-before-month-leap-year* = (create$ 0 31 60 91 121 152 182 213 244 274 305 335))
    CLIPS> 
    (deffunction days-from-year-begin (?date)
       (bind ?year (string-to-field (sub-string 1 4 ?date)))
       (bind ?month (string-to-field (sub-string 6 7 ?date)))
       (bind ?day (string-to-field (sub-string 9 10 ?date)))
       (if (is-leap-year ?year)
          then
          (return (+ (nth$ ?month ?*days-before-month-leap-year*) ?day))
          else
          (return (+ (nth$ ?month ?*days-before-month*) ?day))))
    CLIPS> 
    (deffunction days-until-year-end (?date)
       (bind ?year (string-to-field (sub-string 1 4 ?date)))
       (bind ?month (string-to-field (sub-string 6 7 ?date)))
       (bind ?day (string-to-field (sub-string 9 10 ?date)))
       (if (is-leap-year ?year)
          then
          (return (- 366 (+ (nth$ ?month ?*days-before-month-leap-year*) ?day)))
          else
          (return (- 365 (+ (nth$ ?month ?*days-before-month*) ?day)))))
    CLIPS> 
    (deffunction date-days-diff (?date1 ?date2)
       (bind ?year1 (string-to-field (sub-string 1 4 ?date1)))
       (bind ?year2 (string-to-field (sub-string 1 4 ?date2))) 
       (if (= ?year1 ?year2)
          then
          (return (- (days-from-year-begin ?date1) (days-from-year-begin ?date2))))
       (if (> ?year1 ?year2)
          then
          (bind ?negate FALSE)
          else
          (bind ?negate TRUE)
          (bind ?temp ?date1)
          (bind ?date1 ?date2)
          (bind ?date2 ?temp)
          (bind ?temp ?year1)
          (bind ?year1 ?year2)
          (bind ?year2 ?temp))
       (bind ?day-count (+ (days-until-year-end ?date2) (days-from-year-begin ?date1)))
       (loop-for-count (?year (+ ?year2 1) (- ?year1 1)) do
          (if (is-leap-year ?year)
             then (bind ?day-count (+ ?day-count 366))
             else (bind ?day-count (+ ?day-count 365))))
       (if ?negate
          then 
          (return (- 0 ?day-count))
          else
          (return ?day-count)))
    CLIPS> 
    (deffunction date-years-diff (?date1 ?date2)
       (bind ?year1 (string-to-field (sub-string 1 4 ?date1)))
       (bind ?year2 (string-to-field (sub-string 1 4 ?date2))) 
       (if (= ?year1 ?year2)
          then
          (return 0))
       (if (> ?year1 ?year2)
          then
          (bind ?negate FALSE)
          else
          (bind ?negate TRUE)
          (bind ?temp ?date1)
          (bind ?date1 ?date2)
          (bind ?date2 ?temp))
       (bind ?year1 (string-to-field (sub-string 1 4 ?date1)))
       (bind ?year2 (string-to-field (sub-string 1 4 ?date2))) 
       (bind ?month1 (string-to-field (sub-string 6 7 ?date1)))
       (bind ?month2 (string-to-field (sub-string 6 7 ?date2))) 
       (bind ?day1 (string-to-field (sub-string 9 10 ?date1)))
       (bind ?day2 (string-to-field (sub-string 9 10 ?date2))) 
       (bind ?years (- ?year1 ?year2))
       (if (= ?month1 ?month2)
          then
          (if (< ?day1 ?day2)
             then
             (bind ?years (- ?years 1)))
          else
          (if (< ?month1 ?month2)
             then
             (bind ?years (- ?years 1))))
    
       (if ?negate
          then (return (- 0 ?years))
          else (return ?years)))
    CLIPS>       
    (deftemplate driver
       (slot name)
       (slot dateBorn))
    CLIPS> 
    (deffacts drivers
       (driver (name "Daniel Silva") (dateBorn "1985-03-04"))
       (driver (name "Carlos Santos") (dateBorn "2000-03-04")))
    CLIPS> 
    (defrule cantDrive
      (driver (name ?name) (dateBorn ?born))
      (test (< (date-years-diff (current-date) ?born) 25))
      =>
      (printout t ?name " is younger than 25" crlf))
    CLIPS> (reset)
    CLIPS> (run)
    Carlos Santos is younger than 25
    CLIPS>