Off-chain - Ethereum Alarm Clock
If you want a scheduler that actually sends a transaction when some time has passed, Ethereum Alarm Clock is the only one I know about.
On-chain - Block number
If you want the least ambiguity, but the exact time in seconds is not important, scheduling based on block number is likely the best. For instance, a function could only be executed if the transaction
block.number is greater than or equal X. Users then know exactly when they can send their transaction simply by monitoring the block numbers.
However, with that method you do not know precisely when that event will happen (in seconds), because block time can vary. You could have a wide variation between the estimate time at which block X will be mined and the actual time at which it is mine if that block is far in the future.
On-chain - Block timestamp
block.timestamp instead could be a better option if you want to know the time in seconds when the function can be executed. You could then tell users after which time and date the function will be executable.
However, there is ambiguity as to which block it will be when the time is reached, even at the very last moment. Users that would want to send a transaction precisely when the function becomes executable will not be able to do so, because you never know if the next block will be just before or just after the time.
Also note that the
block.timestamp can be manipulated a little bit by miners, as mentioned here.