diff --git a/homeassistant/components/schedule/__init__.py b/homeassistant/components/schedule/__init__.py
index 6ad3bcff58e47ee707f1fd2b5428d33118f0501d..f5519e93c3fad83fa2afb57c77524ac76fd9750c 100644
--- a/homeassistant/components/schedule/__init__.py
+++ b/homeassistant/components/schedule/__init__.py
@@ -291,14 +291,17 @@ class Schedule(Entity):
         todays_schedule = self._config.get(WEEKDAY_TO_CONF[now.weekday()], [])
 
         # Determine current schedule state
-        self._attr_state = next(
-            (
-                STATE_ON
-                for time_range in todays_schedule
-                if time_range[CONF_FROM] <= now.time() <= time_range[CONF_TO]
-            ),
-            STATE_OFF,
-        )
+        for time_range in todays_schedule:
+            # The current time should be greater or equal to CONF_FROM.
+            if now.time() < time_range[CONF_FROM]:
+                continue
+            # The current time should be smaller (and not equal) to CONF_TO.
+            # Note that any time in the day is treated as smaller than time.max.
+            if now.time() < time_range[CONF_TO] or time_range[CONF_TO] == time.max:
+                self._attr_state = STATE_ON
+                break
+        else:
+            self._attr_state = STATE_OFF
 
         # Find next event in the schedule, loop over each day (starting with
         # the current day) until the next event has been found.
@@ -319,11 +322,15 @@ class Schedule(Entity):
             if next_event := next(
                 (
                     possible_next_event
-                    for time in times
+                    for timestamp in times
                     if (
                         possible_next_event := (
-                            datetime.combine(now.date(), time, tzinfo=now.tzinfo)
+                            datetime.combine(now.date(), timestamp, tzinfo=now.tzinfo)
                             + timedelta(days=day)
+                            if not timestamp == time.max
+                            # Special case for midnight of the following day.
+                            else datetime.combine(now.date(), time(), tzinfo=now.tzinfo)
+                            + timedelta(days=day + 1)
                         )
                     )
                     > now
diff --git a/tests/components/schedule/test_init.py b/tests/components/schedule/test_init.py
index 5d5de58134935722dbf689ca81021aefa35587bd..0eda21f5ba0bf8ae6de5b826ff4bf014cdd7ebcb 100644
--- a/tests/components/schedule/test_init.py
+++ b/tests/components/schedule/test_init.py
@@ -221,25 +221,14 @@ async def test_events_one_day(
 
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
-    assert state.state == STATE_ON
+    assert state.state == STATE_OFF
     assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T07:00:00-07:00"
 
 
-@pytest.mark.parametrize(
-    "sun_schedule, mon_schedule",
-    (
-        (
-            {CONF_FROM: "23:00:00", CONF_TO: "24:00:00"},
-            {CONF_FROM: "00:00:00", CONF_TO: "01:00:00"},
-        ),
-    ),
-)
-async def test_adjacent(
+async def test_adjacent_cross_midnight(
     hass: HomeAssistant,
     schedule_setup: Callable[..., Coroutine[Any, Any, bool]],
     caplog: pytest.LogCaptureFixture,
-    sun_schedule: dict[str, str],
-    mon_schedule: dict[str, str],
     freezer,
 ) -> None:
     """Test adjacent events don't toggle on->off->on."""
@@ -251,8 +240,8 @@ async def test_adjacent(
                 "from_yaml": {
                     CONF_NAME: "from yaml",
                     CONF_ICON: "mdi:party-popper",
-                    CONF_SUNDAY: sun_schedule,
-                    CONF_MONDAY: mon_schedule,
+                    CONF_SUNDAY: {CONF_FROM: "23:00:00", CONF_TO: "24:00:00"},
+                    CONF_MONDAY: {CONF_FROM: "00:00:00", CONF_TO: "01:00:00"},
                 }
             }
         },
@@ -272,18 +261,70 @@ async def test_adjacent(
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
     assert state.state == STATE_ON
-    assert (
-        state.attributes[ATTR_NEXT_EVENT].isoformat()
-        == "2022-09-04T23:59:59.999999-07:00"
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T00:00:00-07:00"
+
+    freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
+    async_fire_time_changed(hass)
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_ON
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T01:00:00-07:00"
+
+    freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
+    async_fire_time_changed(hass)
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_OFF
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T23:00:00-07:00"
+
+    await hass.async_block_till_done()
+    assert len(state_changes) == 3
+    for event in state_changes[:-1]:
+        assert event.data["new_state"].state == STATE_ON
+    assert state_changes[2].data["new_state"].state == STATE_OFF
+
+
+async def test_adjacent_within_day(
+    hass: HomeAssistant,
+    schedule_setup: Callable[..., Coroutine[Any, Any, bool]],
+    caplog: pytest.LogCaptureFixture,
+    freezer,
+) -> None:
+    """Test adjacent events don't toggle on->off->on."""
+    freezer.move_to("2022-08-30 13:20:00-07:00")
+
+    assert await schedule_setup(
+        config={
+            DOMAIN: {
+                "from_yaml": {
+                    CONF_NAME: "from yaml",
+                    CONF_ICON: "mdi:party-popper",
+                    CONF_SUNDAY: [
+                        {CONF_FROM: "22:00:00", CONF_TO: "22:30:00"},
+                        {CONF_FROM: "22:30:00", CONF_TO: "23:00:00"},
+                    ],
+                }
+            }
+        },
+        items=[],
     )
 
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_OFF
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T22:00:00-07:00"
+
+    state_changes = async_capture_events(hass, EVENT_STATE_CHANGED)
+
     freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
     async_fire_time_changed(hass)
 
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
     assert state.state == STATE_ON
-    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T00:00:00-07:00"
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T22:30:00-07:00"
 
     freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
     async_fire_time_changed(hass)
@@ -291,7 +332,54 @@ async def test_adjacent(
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
     assert state.state == STATE_ON
-    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T01:00:00-07:00"
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T23:00:00-07:00"
+
+    freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
+    async_fire_time_changed(hass)
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_OFF
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T22:00:00-07:00"
+
+    await hass.async_block_till_done()
+    assert len(state_changes) == 3
+    for event in state_changes[:-1]:
+        assert event.data["new_state"].state == STATE_ON
+    assert state_changes[2].data["new_state"].state == STATE_OFF
+
+
+async def test_non_adjacent_within_day(
+    hass: HomeAssistant,
+    schedule_setup: Callable[..., Coroutine[Any, Any, bool]],
+    caplog: pytest.LogCaptureFixture,
+    freezer,
+) -> None:
+    """Test adjacent events don't toggle on->off->on."""
+    freezer.move_to("2022-08-30 13:20:00-07:00")
+
+    assert await schedule_setup(
+        config={
+            DOMAIN: {
+                "from_yaml": {
+                    CONF_NAME: "from yaml",
+                    CONF_ICON: "mdi:party-popper",
+                    CONF_SUNDAY: [
+                        {CONF_FROM: "22:00:00", CONF_TO: "22:15:00"},
+                        {CONF_FROM: "22:30:00", CONF_TO: "23:00:00"},
+                    ],
+                }
+            }
+        },
+        items=[],
+    )
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_OFF
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T22:00:00-07:00"
+
+    state_changes = async_capture_events(hass, EVENT_STATE_CHANGED)
 
     freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
     async_fire_time_changed(hass)
@@ -299,12 +387,38 @@ async def test_adjacent(
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
     assert state.state == STATE_ON
-    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T23:00:00-07:00"
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T22:15:00-07:00"
+
+    freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
+    async_fire_time_changed(hass)
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_OFF
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T22:30:00-07:00"
+
+    freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
+    async_fire_time_changed(hass)
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_ON
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-04T23:00:00-07:00"
+
+    freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
+    async_fire_time_changed(hass)
+
+    state = hass.states.get(f"{DOMAIN}.from_yaml")
+    assert state
+    assert state.state == STATE_OFF
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T22:00:00-07:00"
 
     await hass.async_block_till_done()
     assert len(state_changes) == 4
-    for event in state_changes:
-        assert event.data["new_state"].state == STATE_ON
+    assert state_changes[0].data["new_state"].state == STATE_ON
+    assert state_changes[1].data["new_state"].state == STATE_OFF
+    assert state_changes[2].data["new_state"].state == STATE_ON
+    assert state_changes[3].data["new_state"].state == STATE_OFF
 
 
 @pytest.mark.parametrize(
@@ -348,17 +462,14 @@ async def test_to_midnight(
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
     assert state.state == STATE_ON
-    assert (
-        state.attributes[ATTR_NEXT_EVENT].isoformat()
-        == "2022-09-04T23:59:59.999999-07:00"
-    )
+    assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-05T00:00:00-07:00"
 
     freezer.move_to(state.attributes[ATTR_NEXT_EVENT])
     async_fire_time_changed(hass)
 
     state = hass.states.get(f"{DOMAIN}.from_yaml")
     assert state
-    assert state.state == STATE_ON
+    assert state.state == STATE_OFF
     assert state.attributes[ATTR_NEXT_EVENT].isoformat() == "2022-09-11T00:00:00-07:00"
 
 
@@ -490,8 +601,8 @@ async def test_ws_delete(
     "to, next_event, saved_to",
     (
         ("23:59:59", "2022-08-10T23:59:59-07:00", "23:59:59"),
-        ("24:00", "2022-08-10T23:59:59.999999-07:00", "24:00:00"),
-        ("24:00:00", "2022-08-10T23:59:59.999999-07:00", "24:00:00"),
+        ("24:00", "2022-08-11T00:00:00-07:00", "24:00:00"),
+        ("24:00:00", "2022-08-11T00:00:00-07:00", "24:00:00"),
     ),
 )
 async def test_update(
@@ -560,8 +671,8 @@ async def test_update(
     "to, next_event, saved_to",
     (
         ("14:00:00", "2022-08-15T14:00:00-07:00", "14:00:00"),
-        ("24:00", "2022-08-15T23:59:59.999999-07:00", "24:00:00"),
-        ("24:00:00", "2022-08-15T23:59:59.999999-07:00", "24:00:00"),
+        ("24:00", "2022-08-16T00:00:00-07:00", "24:00:00"),
+        ("24:00:00", "2022-08-16T00:00:00-07:00", "24:00:00"),
     ),
 )
 async def test_ws_create(