Я бы сделал примерно так:
routes (route_id, station_id, arrival_timeshift, departure_timeshift)
routes_regular (route_id, weekday, deparure_time)
routes_irregular (route_id, deparure_date, departure_time)
В первой таблице сами маршруты и время прибытия/отправления от выхода на маршрут, в минутах.
Во второй таблице дни недели и время выходов на маршрут для регулярных маршрутов.
В третьей - дата и время выходов на маршрут для нерегулярных маршрутов.
Рейс ищем примерно так:
SELECT `s`.`route_id`,
ADDTIME(:date, TIME(ADDDATE(IFNULL(`rr`.`departure_time`, `ri`.`departure_time`), INTERVAL `s`.`departire_timeshift` MINUTE)) AS `departure_datetime`
FROM `routes` AS `s`
JOIN `routes` AS `e`
ON `s`.`station_id` = :startStation
AND `e`.`station_id` = :endStation
AND `e`.`route_id` = `s`.`route_id`
AND `e`.`arrival_time` > `s`.`departure_time`
LEFT JOIN `routes_regular` AS `rr`
ON `rr`.`route_id` = `s`.`route_id`
LEFT JOIN `routes_irregular` AS `ri`
ON `ri`.`route_id` = `s`.`route_id`
AND `ri`.`departure_date` <= :date
AND `ri`.`departure_date` > SUBDATE(:date, INTERVAL 1 MONTH)
WHERE DATE(ADDDATE(ADDTIME(`ri`.`departure_date`, `ri`.`departure_time`),
INTERVAL `s`.`departure_timeshift` MINUTE)) = :date
OR (`rr`.`weekday` + FLOOR(HOUR(ADDDATE(`rr`.`departure_time`,
INTERVAL `s`.`departure_timeshift` MINUTE))/24)) % 7 = WEEKDAY(:date)