Esse tipo de problema é um campo minado de casos extremos que eu sempre delego a lógica para algo como IceCube (https://github.com/seejohnrun/ice_cube ). Ele é feito para lidar com esses tipos de agendamentos recorrentes e vem com suporte fácil para serialização etc.