diff --git a/homeassistant/components/energy/sensor.py b/homeassistant/components/energy/sensor.py
index c97b67287d14b1c98d02e1109cb7a45dab29fcc8..71e385f2fec2b8d4881831ab04771cff550ae196 100644
--- a/homeassistant/components/energy/sensor.py
+++ b/homeassistant/components/energy/sensor.py
@@ -2,6 +2,7 @@
 from __future__ import annotations
 
 import asyncio
+from collections.abc import Callable
 import copy
 from dataclasses import dataclass
 import logging
@@ -22,6 +23,7 @@ from homeassistant.const import (
     VOLUME_GALLONS,
     VOLUME_LITERS,
     UnitOfEnergy,
+    UnitOfVolume,
 )
 from homeassistant.core import (
     HomeAssistant,
@@ -34,29 +36,35 @@ from homeassistant.helpers import entity_registry as er
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.event import async_track_state_change_event
 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
+from homeassistant.util import unit_conversion
 import homeassistant.util.dt as dt_util
+from homeassistant.util.unit_system import METRIC_SYSTEM
 
 from .const import DOMAIN
 from .data import EnergyManager, async_get_manager
 
-SUPPORTED_STATE_CLASSES = [
+SUPPORTED_STATE_CLASSES = {
     SensorStateClass.MEASUREMENT,
     SensorStateClass.TOTAL,
     SensorStateClass.TOTAL_INCREASING,
-]
-VALID_ENERGY_UNITS = [
+}
+VALID_ENERGY_UNITS: set[str] = {
     UnitOfEnergy.WATT_HOUR,
     UnitOfEnergy.KILO_WATT_HOUR,
     UnitOfEnergy.MEGA_WATT_HOUR,
     UnitOfEnergy.GIGA_JOULE,
-]
-VALID_ENERGY_UNITS_GAS = [VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS] + VALID_ENERGY_UNITS
-VALID_VOLUME_UNITS_WATER = [
+}
+VALID_ENERGY_UNITS_GAS = {
+    VOLUME_CUBIC_FEET,
+    VOLUME_CUBIC_METERS,
+    *VALID_ENERGY_UNITS,
+}
+VALID_VOLUME_UNITS_WATER = {
     VOLUME_CUBIC_FEET,
     VOLUME_CUBIC_METERS,
     VOLUME_GALLONS,
     VOLUME_LITERS,
-]
+}
 _LOGGER = logging.getLogger(__name__)
 
 
@@ -252,8 +260,24 @@ class EnergyCostSensor(SensorEntity):
         self.async_write_ha_state()
 
     @callback
-    def _update_cost(self) -> None:  # noqa: C901
+    def _update_cost(self) -> None:
         """Update incurred costs."""
+        if self._adapter.source_type == "grid":
+            valid_units = VALID_ENERGY_UNITS
+            default_price_unit: str | None = UnitOfEnergy.KILO_WATT_HOUR
+
+        elif self._adapter.source_type == "gas":
+            valid_units = VALID_ENERGY_UNITS_GAS
+            # No conversion for gas.
+            default_price_unit = None
+
+        elif self._adapter.source_type == "water":
+            valid_units = VALID_VOLUME_UNITS_WATER
+            if self.hass.config.units is METRIC_SYSTEM:
+                default_price_unit = UnitOfVolume.CUBIC_METERS
+            else:
+                default_price_unit = UnitOfVolume.GALLONS
+
         energy_state = self.hass.states.get(
             cast(str, self._config[self._adapter.stat_energy_key])
         )
@@ -298,52 +322,27 @@ class EnergyCostSensor(SensorEntity):
             except ValueError:
                 return
 
-            if energy_price_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, "").endswith(
-                f"/{UnitOfEnergy.WATT_HOUR}"
-            ):
-                energy_price *= 1000.0
-
-            if energy_price_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, "").endswith(
-                f"/{UnitOfEnergy.MEGA_WATT_HOUR}"
-            ):
-                energy_price /= 1000.0
+            energy_price_unit: str | None = energy_price_state.attributes.get(
+                ATTR_UNIT_OF_MEASUREMENT, ""
+            ).partition("/")[2]
 
-            if energy_price_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, "").endswith(
-                f"/{UnitOfEnergy.GIGA_JOULE}"
-            ):
-                energy_price /= 1000 / 3.6
+            # For backwards compatibility we don't validate the unit of the price
+            # If it is not valid, we assume it's our default price unit.
+            if energy_price_unit not in valid_units:
+                energy_price_unit = default_price_unit
 
         else:
-            energy_price_state = None
             energy_price = cast(float, self._config["number_energy_price"])
+            energy_price_unit = default_price_unit
 
         if self._last_energy_sensor_state is None:
             # Initialize as it's the first time all required entities are in place.
             self._reset(energy_state)
             return
 
-        energy_unit = energy_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
-
-        if self._adapter.source_type == "grid":
-            if energy_unit not in VALID_ENERGY_UNITS:
-                energy_unit = None
-
-        elif self._adapter.source_type == "gas":
-            if energy_unit not in VALID_ENERGY_UNITS_GAS:
-                energy_unit = None
-
-        elif self._adapter.source_type == "water":
-            if energy_unit not in VALID_VOLUME_UNITS_WATER:
-                energy_unit = None
-
-        if energy_unit == UnitOfEnergy.WATT_HOUR:
-            energy_price /= 1000
-        elif energy_unit == UnitOfEnergy.MEGA_WATT_HOUR:
-            energy_price *= 1000
-        elif energy_unit == UnitOfEnergy.GIGA_JOULE:
-            energy_price *= 1000 / 3.6
+        energy_unit: str | None = energy_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
 
-        if energy_unit is None:
+        if energy_unit is None or energy_unit not in valid_units:
             if not self._wrong_unit_reported:
                 self._wrong_unit_reported = True
                 _LOGGER.warning(
@@ -373,10 +372,30 @@ class EnergyCostSensor(SensorEntity):
             energy_state_copy = copy.copy(energy_state)
             energy_state_copy.state = "0.0"
             self._reset(energy_state_copy)
+
         # Update with newly incurred cost
         old_energy_value = float(self._last_energy_sensor_state.state)
         cur_value = cast(float, self._attr_native_value)
-        self._attr_native_value = cur_value + (energy - old_energy_value) * energy_price
+
+        if energy_price_unit is None:
+            converted_energy_price = energy_price
+        else:
+            if self._adapter.source_type == "grid":
+                converter: Callable[
+                    [float, str, str], float
+                ] = unit_conversion.EnergyConverter.convert
+            elif self._adapter.source_type in ("gas", "water"):
+                converter = unit_conversion.VolumeConverter.convert
+
+            converted_energy_price = converter(
+                energy_price,
+                energy_unit,
+                energy_price_unit,
+            )
+
+        self._attr_native_value = (
+            cur_value + (energy - old_energy_value) * converted_energy_price
+        )
 
         self._last_energy_sensor_state = energy_state
 
diff --git a/tests/components/energy/test_sensor.py b/tests/components/energy/test_sensor.py
index 14a04ea74c632620b88d680990e54aa26488aac7..0108dd1de7693c8469767daee4b2df503689b29e 100644
--- a/tests/components/energy/test_sensor.py
+++ b/tests/components/energy/test_sensor.py
@@ -19,11 +19,13 @@ from homeassistant.const import (
     STATE_UNKNOWN,
     VOLUME_CUBIC_FEET,
     VOLUME_CUBIC_METERS,
+    VOLUME_GALLONS,
     UnitOfEnergy,
 )
 from homeassistant.helpers import entity_registry as er
 from homeassistant.setup import async_setup_component
 import homeassistant.util.dt as dt_util
+from homeassistant.util.unit_system import METRIC_SYSTEM, US_CUSTOMARY_SYSTEM
 
 from tests.components.recorder.common import async_wait_recording_done
 
@@ -832,7 +834,10 @@ async def test_cost_sensor_handle_price_units(
     assert state.state == "20.0"
 
 
-@pytest.mark.parametrize("unit", (VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS))
+@pytest.mark.parametrize(
+    "unit",
+    (VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS),
+)
 async def test_cost_sensor_handle_gas(
     setup_integration, hass, hass_storage, unit
 ) -> None:
@@ -933,13 +938,22 @@ async def test_cost_sensor_handle_gas_kwh(
     assert state.state == "50.0"
 
 
-@pytest.mark.parametrize("unit", (VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS))
+@pytest.mark.parametrize(
+    "unit_system,usage_unit,growth",
+    (
+        # 1 cubic foot = 7.47 gl, 100 ft3 growth @ 0.5/ft3:
+        (US_CUSTOMARY_SYSTEM, VOLUME_CUBIC_FEET, 374.025974025974),
+        (US_CUSTOMARY_SYSTEM, VOLUME_GALLONS, 50.0),
+        (METRIC_SYSTEM, VOLUME_CUBIC_METERS, 50.0),
+    ),
+)
 async def test_cost_sensor_handle_water(
-    setup_integration, hass, hass_storage, unit
+    setup_integration, hass, hass_storage, unit_system, usage_unit, growth
 ) -> None:
     """Test water cost price from sensor entity."""
+    hass.config.units = unit_system
     energy_attributes = {
-        ATTR_UNIT_OF_MEASUREMENT: unit,
+        ATTR_UNIT_OF_MEASUREMENT: usage_unit,
         ATTR_STATE_CLASS: SensorStateClass.TOTAL_INCREASING,
     }
     energy_data = data.EnergyManager.default_preferences()
@@ -981,7 +995,7 @@ async def test_cost_sensor_handle_water(
     await hass.async_block_till_done()
 
     state = hass.states.get("sensor.water_consumption_cost")
-    assert state.state == "50.0"
+    assert float(state.state) == pytest.approx(growth)
 
 
 @pytest.mark.parametrize("state_class", [None])