Repository: apache/airflow (Python)

Issue:
CLI command "airflow dags next-execution"  give unexpected results with paused DAG and catchup=False
### Apache Airflow version

2.2.2

### What happened

Current time 16:54 UTC
Execution Schedule: * * * * *
Last Run: 16:19 UTC
DAG Paused
Catchup=False

`airflow dags next-execution sample_dag`
returns
```
[INFO] Please be reminded this DAG is PAUSED now.
2022-03-22T16:20:00+00:00
```

### What you think should happen instead

I would expect
```
[INFO] Please be reminded this DAG is PAUSED now.
2022-03-22T16:53:00+00:00
```
To be returned since when you unpause the DAG that is the next executed DAG

### How to reproduce

Create a simple sample dag with a schedule of * * * * * and pause with catchup=False and wait a few minutes, then run 
`airflow dags next-execution sample_dag`

### Operating System

Debian

### Versions of Apache Airflow Providers

Airflow 2.2.2

### Deployment

Astronomer

### Deployment details

_No response_

### 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)



Discussion: I believe this same issue is showing through the UI, the"next run" on any of the dag views has the same datetime as the 'next-execution' cli command. 
I guess the viable solution would be to add a flag to optionally respect catchup (and perhaps emit a warning when the command is run without the option but with `catchup=False`, to tell the user to explicitly specify the behaviour).
@frankbreetz  - marked it as "good first issue" - so maybe someone can implement it. But maybe you would like to fix it and become contributor? 
I may need some help, but go ahead and sign me up
@uranusjr any preference for the cli flag? I was thinking -r for "respect catchup", but that doesn't seem great
Here is a PR (is this the correct way to do this?)

https://github.com/apache/airflow/pull/22666
I'd not add a short option for now. Short options are overrated and don't need to exist anyway.
> I'd not add a short option for now. Short options are overrated and don't need to exist anyway.

Very much agree. Short options are only for really often used flags that are supposed to be hand-typed and remembered by the users by heart. Can't imagine anyone remembering shorthand for "respect catchup". 
@frankbreetz are you still working on the PR?
@eladkal @potiuk seems like the issue and PR are both still open. Can I take it over?

I won't have time for this anytime soon, feel free to take it over
Assigne you @mrmammadov 
@mrmammadov are you still working on this?
Mind if I take-over?
@boushphong please go ahead
I created a PR for this issue at: https://github.com/apache/airflow/pull/30117
Do you guys mind taking a look? @eladkal @potiuk . Cheers




Fix (patch):
diff --git a/airflow/cli/commands/dag_command.py b/airflow/cli/commands/dag_command.py
index 4a9a1f2c12d74..ef891fba62832 100644
--- a/airflow/cli/commands/dag_command.py
+++ b/airflow/cli/commands/dag_command.py
@@ -27,7 +27,6 @@
 
 from graphviz.dot import Dot
 from sqlalchemy.orm import Session
-from sqlalchemy.sql.functions import func
 
 from airflow import settings
 from airflow.api.client import get_current_api_client
@@ -38,6 +37,7 @@
 from airflow.models import DagBag, DagModel, DagRun, TaskInstance
 from airflow.models.dag import DAG
 from airflow.models.serialized_dag import SerializedDagModel
+from airflow.timetables.base import DataInterval
 from airflow.utils import cli as cli_utils, timezone
 from airflow.utils.cli import get_dag, get_dags, process_subdir, sigint_handler, suppress_logs_and_warning
 from airflow.utils.dot_renderer import render_dag, render_dag_dependencies
@@ -296,36 +296,26 @@ def dag_next_execution(args):
         print("[INFO] Please be reminded this DAG is PAUSED now.", file=sys.stderr)
 
     with create_session() as session:
-        max_date_subq = (
-            session.query(func.max(DagRun.execution_date).label("max_date"))
-            .filter(DagRun.dag_id == dag.dag_id)
-            .subquery()
-        )
-        max_date_run: DagRun | None = (
-            session.query(DagRun)
-            .filter(DagRun.dag_id == dag.dag_id, DagRun.execution_date == max_date_subq.c.max_date)
-            .one_or_none()
-        )
-
-        if max_date_run is None:
-            print("[WARN] Only applicable when there is execution record found for the DAG.", file=sys.stderr)
+        last_parsed_dag: DagModel = session.query(DagModel).filter(DagModel.dag_id == dag.dag_id).one()
+
+    def print_execution_interval(interval: DataInterval | None):
+        if interval is None:
+            print(
+                "[WARN] No following schedule can be found. "
+                "This DAG may have schedule interval '@once' or `None`.",
+                file=sys.stderr,
+            )
             print(None)
             return
+        print(interval.start.isoformat())
 
-    next_info = dag.next_dagrun_info(dag.get_run_data_interval(max_date_run), restricted=False)
-    if next_info is None:
-        print(
-            "[WARN] No following schedule can be found. "
-            "This DAG may have schedule interval '@once' or `None`.",
-            file=sys.stderr,
-        )
-        print(None)
-        return
+    next_interval = dag.get_next_data_interval(last_parsed_dag)
+    print_execution_interval(next_interval)
 
-    print(next_info.logical_date.isoformat())
-    for _ in range(1, args.num_executions):
-        next_info = dag.next_dagrun_info(next_info.data_interval, restricted=False)
-        print(next_info.logical_date.isoformat())
+    for i in range(1, args.num_executions):
+        next_info = dag.next_dagrun_info(next_interval, restricted=False)
+        next_interval = None if next_info is None else next_info.data_interval
+        print_execution_interval(next_interval)
 
 
 @cli_utils.action_cli