I've written a few programs along these lines.
I suggest #2. All you need to to is keep a list of times that events are "due" at, and every X amount of time (depending on your resolution) check your list for "now" events. You can pick up some optimization if you can guarantee the list is sorted, and that each event on the list is due exactly once. Otherwise, if you have recurring events, you have to make sure you cover your window. What I mean is, if you have an event that is due at 11:30 am, and you're checking every seconds, then it's possible that you could check at 11:29:59, and then not again until 11:31:01, due to the inprecision of the CPU time-slices. So you'll need to be sure that one of those checks (11:29 or 11:31) still picks up the 11:30 hit, and that ONLY one of them does (i.e., you don't run at both 11:29 and 11:31).
The advantage this approach has over checking only on times you know to be on your list is that allows your list to be modified by 3rd parties without your knowledge, and your event handler will continue to 'just work'.