Using IO Safely With Heavily Stateful Problem

The only IO you are using is getCurrentTime. You can simply add the current time as an argument to the loanBookToPatron function:

loanBookToPatron :: Book -> Integer -> Date -> Patron -> Patron
loanBookToPatron bk days now p =
    let duedate = Time.addUTCTime (fromInteger days * Time.nominalDay) now
        lo = Loan bk now duedate
        addedLoan = lo : borrowed p
    in p {borrowed = addedLoan}
6 Likes