### Apache Airflow version

2.2.0 (latest released)

### Operating System

Mac

### Versions of Apache Airflow Providers

_No response_

### Deployment

Other Docker-based deployment

### Deployment details

_No response_

### What happened

Getting an exception when returning None from next_dagrun_info in a custom timetable. The timetable protocol says that when None is returned a DagRun will not happen but right now it throws an exception.

Exception:
```
Traceback (most recent call last):
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/jobs/scheduler_job.py", line 623, in _execute
    self._run_scheduler_loop()
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/jobs/scheduler_job.py", line 704, in _run_scheduler_loop
    num_queued_tis = self._do_scheduling(session)
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/jobs/scheduler_job.py", line 787, in _do_scheduling
    callback_to_run = self._schedule_dag_run(dag_run, session)
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/jobs/scheduler_job.py", line 1039, in _schedule_dag_run
    self._update_dag_next_dagruns(dag, dag_model, active_runs)
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/jobs/scheduler_job.py", line 930, in _update_dag_next_dagruns
    data_interval = dag.get_next_data_interval(dag_model)
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/models/dag.py", line 629, in get_next_data_interval
    return self.infer_automated_data_interval(dag_model.next_dagrun)
  File "/home/airflow/.local/lib/python3.9/site-packages/airflow/models/dag.py", line 671, in infer_automated_data_interval
    raise ValueError(f"Not a valid timetable: {self.timetable!r}")
ValueError: Not a valid timetable: <my_timetables.workday_timetable.WorkdayTimetable object at 0x7f42b1f02430>
```

### What you expected to happen

DagRun to not happen.

### How to reproduce

Create a custom timetable and return None in next_dagrun_info after a few DagRuns are created by that timetable

### Anything else

_No response_

### Are you willing to submit PR?

- [ ] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

airflow/models/dag.py
most_recent_runs = {run.dag_id: run for run in most_recent_runs_iter}
        
        num_active_runs = DagRun.active_runs_of_dags(dag_ids=existing_dag_ids, session=session)
        filelocs = []
        for orm_dag in sorted(orm_dags, key=lambda d: d.dag_id):
            dag = dag_by_ids[orm_dag.dag_id]
            filelocs.append(dag.fileloc)
            if dag.is_subdag:
                orm_dag.is_subdag = True
                orm_dag.fileloc = dag.parent_dag.fileloc  
                orm_dag.root_dag_id = dag.parent_dag.dag_id  
                orm_dag.owners = dag.parent_dag.owner  
            else:
                orm_dag.is_subdag = False
                orm_dag.fileloc = dag.fileloc
                orm_dag.owners = dag.owner
            orm_dag.is_active = True
            orm_dag.last_parsed_time = timezone.utcnow()
            orm_dag.default_view = dag.default_view
            orm_dag.description = dag.description
            orm_dag.schedule_interval = dag.schedule_interval
            orm_dag.max_active_tasks = dag.max_active_tasks
            orm_dag.max_active_runs = dag.max_active_runs
            orm_dag.has_task_concurrency_limits = any(t.max_active_tis_per_dag is not None for t in dag.tasks)
            run: Optional[DagRun] = most_recent_runs.get(dag.dag_id)
            if run is None:
                data_interval = None
            else:
                data_interval = dag.get_run_data_interval(run)
            if num_active_runs.get(dag.dag_id, 0) >= orm_dag.max_active_runs: