diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarBestPriceResult.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarBestPriceResult.java
index b14c4fe584a..ef9a866ca5f 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarBestPriceResult.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarBestPriceResult.java
@@ -12,6 +12,8 @@
  */
 package org.openhab.binding.awattar.internal;
 
+import java.time.Instant;
+
 import org.eclipse.jdt.annotation.NonNullByDefault;
 
 /**
@@ -24,7 +26,7 @@ public abstract class AwattarBestPriceResult {
     private long start;
     private long end;
 
-    public AwattarBestPriceResult() {
+    protected AwattarBestPriceResult() {
     }
 
     public long getStart() {
@@ -47,7 +49,18 @@ public abstract class AwattarBestPriceResult {
         }
     }
 
-    public abstract boolean isActive();
+    /**
+     * Returns true if the best price is active.
+     *
+     * @param pointInTime the current time
+     * @return true if the best price is active, false otherwise
+     */
+    public abstract boolean isActive(Instant pointInTime);
 
+    /**
+     * Returns the hours of the best price.
+     *
+     * @return the hours of the best price as a string
+     */
     public abstract String getHours();
 }
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarConsecutiveBestPriceResult.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarConsecutiveBestPriceResult.java
index 49e3d52126a..b648f285508 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarConsecutiveBestPriceResult.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarConsecutiveBestPriceResult.java
@@ -76,8 +76,8 @@ public class AwattarConsecutiveBestPriceResult extends AwattarBestPriceResult {
     }
 
     @Override
-    public boolean isActive() {
-        return contains(Instant.now().toEpochMilli());
+    public boolean isActive(Instant pointInTime) {
+        return contains(pointInTime.toEpochMilli());
     }
 
     public boolean contains(long timestamp) {
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarNonConsecutiveBestPriceResult.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarNonConsecutiveBestPriceResult.java
index 20d79272b58..01ed9197c58 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarNonConsecutiveBestPriceResult.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarNonConsecutiveBestPriceResult.java
@@ -32,7 +32,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
 public class AwattarNonConsecutiveBestPriceResult extends AwattarBestPriceResult {
     private final List<AwattarPrice> members;
     private final ZoneId zoneId;
-    private boolean sorted = true;
 
     public AwattarNonConsecutiveBestPriceResult(List<AwattarPrice> prices, int length, boolean inverted,
             ZoneId zoneId) {
@@ -57,15 +56,14 @@ public class AwattarNonConsecutiveBestPriceResult extends AwattarBestPriceResult
     }
 
     private void addMember(AwattarPrice member) {
-        sorted = false;
         members.add(member);
         updateStart(member.timerange().start());
         updateEnd(member.timerange().end());
     }
 
     @Override
-    public boolean isActive() {
-        return members.stream().anyMatch(x -> x.timerange().contains(Instant.now().toEpochMilli()));
+    public boolean isActive(Instant pointInTime) {
+        return members.stream().anyMatch(x -> x.timerange().contains(pointInTime.toEpochMilli()));
     }
 
     @Override
@@ -73,16 +71,9 @@ public class AwattarNonConsecutiveBestPriceResult extends AwattarBestPriceResult
         return String.format("NonConsecutiveBestpriceResult with %s", members.toString());
     }
 
-    private void sort() {
-        if (!sorted) {
-            members.sort(Comparator.comparingLong(p -> p.timerange().start()));
-        }
-    }
-
     @Override
     public String getHours() {
         boolean second = false;
-        sort();
         StringBuilder res = new StringBuilder();
 
         for (AwattarPrice price : members) {
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarUtil.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarUtil.java
index be9661d51b3..d4128e979d0 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarUtil.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/AwattarUtil.java
@@ -20,7 +20,6 @@ import java.time.temporal.ChronoUnit;
 import javax.measure.quantity.Time;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.i18n.TimeZoneProvider;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.unit.Units;
 
@@ -32,9 +31,9 @@ import org.openhab.core.library.unit.Units;
 @NonNullByDefault
 public class AwattarUtil {
 
-    public static long getMillisToNextMinute(int mod, TimeZoneProvider timeZoneProvider) {
+    public static long getMillisToNextMinute(int mod, ZoneId zoneId) {
         long now = Instant.now().toEpochMilli();
-        ZonedDateTime dt = ZonedDateTime.now(timeZoneProvider.getTimeZone()).truncatedTo(ChronoUnit.MINUTES);
+        ZonedDateTime dt = ZonedDateTime.now(zoneId).truncatedTo(ChronoUnit.MINUTES);
         int min = dt.getMinute();
         int offset = min % mod;
         offset = offset == 0 ? mod : offset;
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/api/AwattarApi.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/api/AwattarApi.java
index b56454d2939..d2cfb91362c 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/api/AwattarApi.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/api/AwattarApi.java
@@ -15,9 +15,8 @@ package org.openhab.binding.awattar.internal.api;
 import static org.eclipse.jetty.http.HttpMethod.GET;
 import static org.eclipse.jetty.http.HttpStatus.OK_200;
 
-import java.time.LocalDate;
-import java.time.ZoneId;
 import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.Comparator;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -31,6 +30,7 @@ import org.eclipse.jetty.client.api.ContentResponse;
 import org.openhab.binding.awattar.internal.AwattarBridgeConfiguration;
 import org.openhab.binding.awattar.internal.AwattarPrice;
 import org.openhab.binding.awattar.internal.dto.AwattarApiData;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.binding.awattar.internal.dto.Datum;
 import org.openhab.binding.awattar.internal.handler.TimeRange;
 import org.slf4j.Logger;
@@ -58,7 +58,7 @@ public class AwattarApi {
     private double vatFactor;
     private double basePrice;
 
-    private ZoneId zone;
+    private AwattarTimeProvider timeProvider;
 
     private Gson gson;
 
@@ -79,8 +79,8 @@ public class AwattarApi {
      * @param httpClient the HTTP client to use
      * @param zone the time zone to use
      */
-    public AwattarApi(HttpClient httpClient, ZoneId zone, AwattarBridgeConfiguration config) {
-        this.zone = zone;
+    public AwattarApi(HttpClient httpClient, AwattarTimeProvider timeProvider, AwattarBridgeConfiguration config) {
+        this.timeProvider = timeProvider;
         this.httpClient = httpClient;
 
         this.gson = new Gson();
@@ -112,7 +112,7 @@ public class AwattarApi {
     public SortedSet<AwattarPrice> getData() throws AwattarApiException {
         try {
             // we start one day in the past to cover ranges that already started yesterday
-            ZonedDateTime zdt = LocalDate.now(zone).atStartOfDay(zone).minusDays(1);
+            ZonedDateTime zdt = timeProvider.getZonedDateTimeNow().truncatedTo(ChronoUnit.DAYS).minusDays(1);
             long start = zdt.toInstant().toEpochMilli();
             // Starting from midnight yesterday we add three days so that the range covers
             // the whole next day.
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/dto/AwattarTimeProvider.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/dto/AwattarTimeProvider.java
new file mode 100644
index 00000000000..084b924dd57
--- /dev/null
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/dto/AwattarTimeProvider.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010-2025 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.awattar.internal.dto;
+
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.i18n.TimeZoneProvider;
+
+/**
+ * The {@link AwattarTimeProvider} provides a time provider for aWATTar
+ *
+ * @author Thomas Leber - Initial contribution
+ */
+@NonNullByDefault
+public class AwattarTimeProvider {
+
+    private TimeZoneProvider timeZoneProvider;
+
+    public AwattarTimeProvider(TimeZoneProvider timeZoneProvider) {
+        this.timeZoneProvider = timeZoneProvider;
+    }
+
+    /**
+     * Get the current zone id.
+     *
+     * @return the current zone id
+     */
+    public ZoneId getZoneId() {
+        return timeZoneProvider.getTimeZone();
+    }
+
+    /**
+     * Get the current instant.
+     *
+     * @return the current instant
+     */
+    public Instant getInstantNow() {
+        return Instant.now();
+    }
+
+    /**
+     * Get the current zoned date time.
+     *
+     * @return the current zoned date time
+     */
+    public ZonedDateTime getZonedDateTimeNow() {
+        return Instant.now().atZone(getZoneId());
+    }
+}
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBestPriceHandler.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBestPriceHandler.java
index c166a51cc85..9de71f8c32e 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBestPriceHandler.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBestPriceHandler.java
@@ -39,7 +39,7 @@ import org.openhab.binding.awattar.internal.AwattarBestPriceResult;
 import org.openhab.binding.awattar.internal.AwattarConsecutiveBestPriceResult;
 import org.openhab.binding.awattar.internal.AwattarNonConsecutiveBestPriceResult;
 import org.openhab.binding.awattar.internal.AwattarPrice;
-import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.library.types.DateTimeType;
 import org.openhab.core.library.types.OnOffType;
 import org.openhab.core.library.types.QuantityType;
@@ -70,14 +70,13 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
     private static final int THING_REFRESH_INTERVAL = 60;
 
     private final Logger logger = LoggerFactory.getLogger(AwattarBestPriceHandler.class);
+    private final AwattarTimeProvider timeProvider;
 
     private @Nullable ScheduledFuture<?> thingRefresher;
 
-    private final TimeZoneProvider timeZoneProvider;
-
-    public AwattarBestPriceHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
+    public AwattarBestPriceHandler(Thing thing, AwattarTimeProvider timeProvider) {
         super(thing);
-        this.timeZoneProvider = timeZoneProvider;
+        this.timeProvider = timeProvider;
     }
 
     @Override
@@ -97,7 +96,7 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
                  * here
                  */
                 thingRefresher = scheduler.scheduleAtFixedRate(this::refreshChannels,
-                        getMillisToNextMinute(1, timeZoneProvider), THING_REFRESH_INTERVAL * 1000L,
+                        getMillisToNextMinute(1, timeProvider.getZoneId()), THING_REFRESH_INTERVAL * 1000L,
                         TimeUnit.MILLISECONDS);
             }
         }
@@ -141,7 +140,7 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
             return;
         }
 
-        ZoneId zoneId = bridgeHandler.getTimeZone();
+        ZoneId zoneId = timeProvider.getZoneId();
 
         AwattarBestPriceConfiguration config = getConfigAs(AwattarBestPriceConfiguration.class);
         TimeRange timerange = getRange(config.rangeStart, config.rangeDuration, zoneId);
@@ -163,7 +162,7 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
         long diff;
         switch (channelId) {
             case CHANNEL_ACTIVE:
-                state = OnOffType.from(result.isActive());
+                state = OnOffType.from(result.isActive(timeProvider.getInstantNow()));
                 break;
             case CHANNEL_START:
                 state = new DateTimeType(Instant.ofEpochMilli(result.getStart()));
@@ -172,7 +171,7 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
                 state = new DateTimeType(Instant.ofEpochMilli(result.getEnd()));
                 break;
             case CHANNEL_COUNTDOWN:
-                diff = result.getStart() - Instant.now().toEpochMilli();
+                diff = result.getStart() - timeProvider.getInstantNow().toEpochMilli();
                 if (diff >= 0) {
                     state = getDuration(diff);
                 } else {
@@ -180,8 +179,8 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
                 }
                 break;
             case CHANNEL_REMAINING:
-                if (result.isActive()) {
-                    diff = result.getEnd() - Instant.now().toEpochMilli();
+                if (result.isActive(timeProvider.getInstantNow())) {
+                    diff = result.getEnd() - timeProvider.getInstantNow().toEpochMilli();
                     state = getDuration(diff);
                 } else {
                     state = QuantityType.valueOf(0, Units.MINUTE);
@@ -216,20 +215,39 @@ public class AwattarBestPriceHandler extends BaseThingHandler {
         return result;
     }
 
+    /**
+     * Returns the time range for the given start hour and duration.
+     *
+     * @param start the start hour (0-23)
+     * @param duration the duration in hours
+     * @param zoneId the time zone to use
+     * @return the range
+     */
     protected TimeRange getRange(int start, int duration, ZoneId zoneId) {
-        ZonedDateTime startCal = getCalendarForHour(start, zoneId);
-        ZonedDateTime endCal = startCal.plusHours(duration);
-        ZonedDateTime now = ZonedDateTime.now(zoneId);
+        ZonedDateTime startTime = getStartTime(start, zoneId);
+        ZonedDateTime endTime = startTime.plusHours(duration);
+        ZonedDateTime now = timeProvider.getZonedDateTimeNow();
         if (now.getHour() < start) {
             // we are before the range, so we might be still within the last range
-            startCal = startCal.minusDays(1);
-            endCal = endCal.minusDays(1);
+            startTime = startTime.minusDays(1);
+            endTime = endTime.minusDays(1);
         }
-        if (endCal.toInstant().toEpochMilli() < Instant.now().toEpochMilli()) {
+        if (endTime.isBefore(now)) {
             // span is in the past, add one day
-            startCal = startCal.plusDays(1);
-            endCal = endCal.plusDays(1);
+            startTime = startTime.plusDays(1);
+            endTime = endTime.plusDays(1);
         }
-        return new TimeRange(startCal.toInstant().toEpochMilli(), endCal.toInstant().toEpochMilli());
+        return new TimeRange(startTime.toInstant().toEpochMilli(), endTime.toInstant().toEpochMilli());
+    }
+
+    /**
+     * Returns the start time for the given hour.
+     *
+     * @param start the hour. Must be between 0 and 23.
+     * @param zoneId the time zone
+     * @return the start time
+     */
+    protected ZonedDateTime getStartTime(int start, ZoneId zoneId) {
+        return getCalendarForHour(start, zoneId);
     }
 }
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandler.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandler.java
index db5eee87cde..324a758dffc 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandler.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandler.java
@@ -16,12 +16,11 @@ import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANN
 import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_TOTAL_NET;
 
 import java.time.Instant;
-import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.SortedSet;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
+import java.util.function.ToDoubleFunction;
 
 import javax.measure.Unit;
 
@@ -32,7 +31,7 @@ import org.openhab.binding.awattar.internal.AwattarBridgeConfiguration;
 import org.openhab.binding.awattar.internal.AwattarPrice;
 import org.openhab.binding.awattar.internal.api.AwattarApi;
 import org.openhab.binding.awattar.internal.api.AwattarApi.AwattarApiException;
-import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.unit.CurrencyUnits;
 import org.openhab.core.thing.Bridge;
@@ -65,20 +64,20 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
 
     private final Logger logger = LoggerFactory.getLogger(AwattarBridgeHandler.class);
     private final HttpClient httpClient;
+    private final AwattarTimeProvider timeProvider;
 
     private @Nullable ScheduledFuture<?> dataRefresher;
     private Instant lastRefresh = Instant.EPOCH;
 
     // This cache stores price data for up to two days
     private @Nullable SortedSet<AwattarPrice> prices;
-    private ZoneId zone;
 
     private @Nullable AwattarApi awattarApi;
 
-    public AwattarBridgeHandler(Bridge thing, HttpClient httpClient, TimeZoneProvider timeZoneProvider) {
+    public AwattarBridgeHandler(Bridge thing, HttpClient httpClient, AwattarTimeProvider timeProvider) {
         super(thing);
         this.httpClient = httpClient;
-        zone = timeZoneProvider.getTimeZone();
+        this.timeProvider = timeProvider;
     }
 
     @Override
@@ -87,7 +86,7 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
         AwattarBridgeConfiguration config = getConfigAs(AwattarBridgeConfiguration.class);
 
         try {
-            awattarApi = new AwattarApi(httpClient, zone, config);
+            awattarApi = new AwattarApi(httpClient, timeProvider, config);
 
             dataRefresher = scheduler.scheduleWithFixedDelay(this::refreshIfNeeded, 0, DATA_REFRESH_INTERVAL * 1000L,
                     TimeUnit.MILLISECONDS);
@@ -154,17 +153,15 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
         return priceUnit;
     }
 
-    private void createAndSendTimeSeries(String channelId, Function<AwattarPrice, Double> valueFunction) {
+    private void createAndSendTimeSeries(String channelId, ToDoubleFunction<AwattarPrice> valueFunction) {
         SortedSet<AwattarPrice> locPrices = getPrices();
         Unit<?> priceUnit = getPriceUnit();
         if (locPrices == null) {
             return;
         }
         TimeSeries timeSeries = new TimeSeries(TimeSeries.Policy.REPLACE);
-        locPrices.forEach(p -> {
-            timeSeries.add(Instant.ofEpochMilli(p.timerange().start()),
-                    new QuantityType<>(valueFunction.apply(p) / 100.0, priceUnit));
-        });
+        locPrices.forEach(p -> timeSeries.add(Instant.ofEpochMilli(p.timerange().start()),
+                new QuantityType<>(valueFunction.applyAsDouble(p) / 100.0, priceUnit)));
         sendTimeSeries(channelId, timeSeries);
     }
 
@@ -186,11 +183,13 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
     private boolean needRefresh() {
         // if the thing is offline, we need to refresh
         if (getThing().getStatus() != ThingStatus.ONLINE) {
+            lastRefresh = timeProvider.getInstantNow();
             return true;
         }
 
         // if the local cache is empty, we need to refresh
         if (prices == null) {
+            lastRefresh = timeProvider.getInstantNow();
             return true;
         }
 
@@ -200,15 +199,15 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
 
         // do not refresh before 15:00, since the prices for the next day are available
         // only after 14:00
-        ZonedDateTime now = ZonedDateTime.now(zone);
+        ZonedDateTime now = timeProvider.getZonedDateTimeNow();
         if (now.getHour() < 15) {
             return false;
         }
 
-        // refresh then every 3 hours, if the last refresh was more than an hour ago
+        // refresh at 15:00, 18:00 and 21:00 if the last refresh was more than an hour ago
         if (now.getHour() % 3 == 0 && lastRefresh.getEpochSecond() < now.minusHours(1).toEpochSecond()) {
             // update the last refresh time
-            lastRefresh = Instant.now();
+            lastRefresh = timeProvider.getInstantNow();
 
             // return true to indicate an update is needed
             return true;
@@ -217,10 +216,6 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
         return false;
     }
 
-    public ZoneId getTimeZone() {
-        return zone;
-    }
-
     @Nullable
     public synchronized SortedSet<AwattarPrice> getPrices() {
         if (prices == null) {
@@ -261,6 +256,7 @@ public class AwattarBridgeHandler extends BaseBridgeHandler {
             switch (channelUID.getId()) {
                 case CHANNEL_MARKET_NET -> createAndSendTimeSeries(CHANNEL_MARKET_NET, AwattarPrice::netPrice);
                 case CHANNEL_TOTAL_NET -> createAndSendTimeSeries(CHANNEL_TOTAL_NET, AwattarPrice::netTotal);
+                default -> logger.warn("Channel {} not supported", channelUID.getId());
             }
         }
     }
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarHandlerFactory.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarHandlerFactory.java
index ec5fac0aa11..94502e60d52 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarHandlerFactory.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarHandlerFactory.java
@@ -21,6 +21,7 @@ import java.util.Set;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.client.HttpClient;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.i18n.TimeZoneProvider;
 import org.openhab.core.io.net.http.HttpClientFactory;
 import org.openhab.core.thing.Bridge;
@@ -50,13 +51,13 @@ public class AwattarHandlerFactory extends BaseThingHandlerFactory {
     private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_PRICE, THING_TYPE_BESTPRICE,
             THING_TYPE_BRIDGE);
     private final HttpClient httpClient;
-    private final TimeZoneProvider timeZoneProvider;
+    private final AwattarTimeProvider timeProvider;
 
     @Activate
     public AwattarHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
             final @Reference TimeZoneProvider timeZoneProvider) {
         this.httpClient = httpClientFactory.getCommonHttpClient();
-        this.timeZoneProvider = timeZoneProvider;
+        this.timeProvider = new AwattarTimeProvider(timeZoneProvider);
     }
 
     @Override
@@ -69,11 +70,11 @@ public class AwattarHandlerFactory extends BaseThingHandlerFactory {
         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
 
         if (THING_TYPE_BRIDGE.equals(thingTypeUID)) {
-            return new AwattarBridgeHandler((Bridge) thing, httpClient, timeZoneProvider);
+            return new AwattarBridgeHandler((Bridge) thing, httpClient, timeProvider);
         } else if (THING_TYPE_PRICE.equals(thingTypeUID)) {
-            return new AwattarPriceHandler(thing, timeZoneProvider);
+            return new AwattarPriceHandler(thing, timeProvider);
         } else if (THING_TYPE_BESTPRICE.equals(thingTypeUID)) {
-            return new AwattarBestPriceHandler(thing, timeZoneProvider);
+            return new AwattarBestPriceHandler(thing, timeProvider);
         }
 
         logger.warn("Unknown thing type {}, not creating handler!", thingTypeUID);
diff --git a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarPriceHandler.java b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarPriceHandler.java
index 8f68fbf1142..0ddf76aad19 100644
--- a/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarPriceHandler.java
+++ b/bundles/org.openhab.binding.awattar/src/main/java/org/openhab/binding/awattar/internal/handler/AwattarPriceHandler.java
@@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.awattar.internal.AwattarPrice;
-import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.thing.Bridge;
 import org.openhab.core.thing.Channel;
@@ -55,15 +55,16 @@ import org.slf4j.LoggerFactory;
  */
 @NonNullByDefault
 public class AwattarPriceHandler extends BaseThingHandler {
+    private final AwattarTimeProvider timeProvider;
+
     private static final int THING_REFRESH_INTERVAL = 60;
     private final Logger logger = LoggerFactory.getLogger(AwattarPriceHandler.class);
 
-    private final TimeZoneProvider timeZoneProvider;
     private @Nullable ScheduledFuture<?> thingRefresher;
 
-    public AwattarPriceHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
+    public AwattarPriceHandler(Thing thing, AwattarTimeProvider timeProvider) {
         super(thing);
-        this.timeZoneProvider = timeZoneProvider;
+        this.timeProvider = timeProvider;
     }
 
     @Override
@@ -90,7 +91,7 @@ public class AwattarPriceHandler extends BaseThingHandler {
                  * here
                  */
                 thingRefresher = scheduler.scheduleAtFixedRate(this::refreshChannels,
-                        getMillisToNextMinute(1, timeZoneProvider), THING_REFRESH_INTERVAL * 1000,
+                        getMillisToNextMinute(1, timeProvider.getZoneId()), THING_REFRESH_INTERVAL * 1000L,
                         TimeUnit.MILLISECONDS);
             }
         }
@@ -139,11 +140,11 @@ public class AwattarPriceHandler extends BaseThingHandler {
         ZonedDateTime target;
 
         if (group.equals(CHANNEL_GROUP_CURRENT)) {
-            target = ZonedDateTime.now(bridgeHandler.getTimeZone());
+            target = timeProvider.getZonedDateTimeNow();
         } else if (group.startsWith("today")) {
-            target = getCalendarForHour(Integer.parseInt(group.substring(5)), bridgeHandler.getTimeZone());
+            target = getCalendarForHour(Integer.parseInt(group.substring(5)), timeProvider.getZoneId());
         } else if (group.startsWith("tomorrow")) {
-            target = getCalendarForHour(Integer.parseInt(group.substring(8)), bridgeHandler.getTimeZone()).plusDays(1);
+            target = getCalendarForHour(Integer.parseInt(group.substring(8)), timeProvider.getZoneId()).plusDays(1);
         } else {
             logger.warn("Unsupported channel group {}", group);
             updateState(channelUID, state);
@@ -153,7 +154,7 @@ public class AwattarPriceHandler extends BaseThingHandler {
         AwattarPrice price = bridgeHandler.getPriceFor(target.toInstant().toEpochMilli());
 
         if (price == null) {
-            logger.trace("No price found for hour {}", target.toString());
+            logger.trace("No price found for hour {}", target);
             updateState(channelUID, state);
             return;
         }
diff --git a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/AwattarBestPriceTest.java b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/AwattarBestPriceTest.java
index c7a20a28590..10edf635dde 100644
--- a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/AwattarBestPriceTest.java
+++ b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/AwattarBestPriceTest.java
@@ -24,6 +24,7 @@ import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
+import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.junit.jupiter.api.Test;
 import org.openhab.binding.awattar.internal.handler.TimeRange;
 
@@ -33,6 +34,7 @@ import org.openhab.binding.awattar.internal.handler.TimeRange;
  *
  * @author Thomas Leber - Initial contribution
  */
+@NonNullByDefault
 public class AwattarBestPriceTest {
 
     private ZoneId zoneId = ZoneId.of("GMT");
@@ -74,7 +76,7 @@ public class AwattarBestPriceTest {
     }
 
     @Test
-    void AwattarConsecutiveBestPriceResult() {
+    void awattarConsecutiveBestPriceResult() {
         int length = 8;
 
         List<AwattarPrice> range = new ArrayList<>(getPrices());
@@ -85,7 +87,7 @@ public class AwattarBestPriceTest {
     }
 
     @Test
-    void AwattarNonConsecutiveBestPriceResult_nonInverted() {
+    void awattarNonConsecutiveBestPriceResultNonInverted() {
         int length = 6;
         boolean inverted = false;
 
@@ -98,7 +100,7 @@ public class AwattarBestPriceTest {
     }
 
     @Test
-    void AwattarNonConsecutiveBestPriceResult_inverted() {
+    void awattarNonConsecutiveBestPriceResultInverted() {
         int length = 4;
         boolean inverted = true;
 
diff --git a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/api/AwattarApiTest.java b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/api/AwattarApiTest.java
index 615317cf6f3..eb8d19f0129 100644
--- a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/api/AwattarApiTest.java
+++ b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/api/AwattarApiTest.java
@@ -17,12 +17,16 @@ import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.time.Instant;
 import java.time.ZoneId;
+import java.time.ZonedDateTime;
 import java.util.Objects;
 import java.util.SortedSet;
 import java.util.concurrent.ExecutionException;
@@ -45,7 +49,7 @@ import org.mockito.quality.Strictness;
 import org.openhab.binding.awattar.internal.AwattarBridgeConfiguration;
 import org.openhab.binding.awattar.internal.AwattarPrice;
 import org.openhab.binding.awattar.internal.api.AwattarApi.AwattarApiException;
-import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.test.java.JavaTest;
 
 /**
@@ -60,10 +64,10 @@ import org.openhab.core.test.java.JavaTest;
 class AwattarApiTest extends JavaTest {
     // API Mocks
     private @Mock @NonNullByDefault({}) HttpClient httpClientMock;
-    private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProviderMock;
     private @Mock @NonNullByDefault({}) Request requestMock;
     private @Mock @NonNullByDefault({}) ContentResponse contentResponseMock;
     private @Mock @NonNullByDefault({}) AwattarBridgeConfiguration config;
+    private @Mock @NonNullByDefault({}) AwattarTimeProvider timeProviderMock;
 
     // sut
     private @NonNullByDefault({}) AwattarApi api;
@@ -86,30 +90,33 @@ class AwattarApiTest extends JavaTest {
         when(requestMock.timeout(10, TimeUnit.SECONDS)).thenReturn(requestMock);
         when(requestMock.send()).thenReturn(contentResponseMock);
 
-        when(timeZoneProviderMock.getTimeZone()).thenReturn(ZoneId.of("GMT+2"));
+        ZonedDateTime zdt = Instant.parse("2024-06-15T12:00:00Z").atZone(ZoneId.of("GMT+2"));
+        when(timeProviderMock.getZonedDateTimeNow()).thenReturn(zdt);
 
         config.basePrice = 0.0;
         config.vatPercent = 0.0;
         config.country = "DE";
 
-        api = new AwattarApi(httpClientMock, ZoneId.of("GMT+2"), config);
+        api = new AwattarApi(httpClientMock, timeProviderMock, config);
     }
 
     @Test
     void testDeUrl() throws AwattarApiException {
         api.getData();
 
-        assertThat(httpClientMock.newRequest("https://api.awattar.de/v1/marketdata"), is(requestMock));
+        verify(httpClientMock, times(1))
+                .newRequest("https://api.awattar.de/v1/marketdata?start=1718316000000&end=1718575200000");
     }
 
     @Test
     void testAtUrl() throws AwattarApiException {
         config.country = "AT";
-        api = new AwattarApi(httpClientMock, ZoneId.of("GMT+2"), config);
+        api = new AwattarApi(httpClientMock, timeProviderMock, config);
 
         api.getData();
 
-        assertThat(httpClientMock.newRequest("https://api.awattar.at/v1/marketdata"), is(requestMock));
+        verify(httpClientMock, times(1))
+                .newRequest("https://api.awattar.at/v1/marketdata?start=1718316000000&end=1718575200000");
     }
 
     @Test
@@ -117,7 +124,7 @@ class AwattarApiTest extends JavaTest {
         config.country = "CH";
 
         IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
-                () -> new AwattarApi(httpClientMock, ZoneId.of("GMT+2"), config));
+                () -> new AwattarApi(httpClientMock, timeProviderMock, config));
         assertThat(thrown.getMessage(), is("Country code must be 'DE' or 'AT'"));
     }
 
diff --git a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerRefreshTest.java b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerRefreshTest.java
index e2d34a095bd..166141ac798 100644
--- a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerRefreshTest.java
+++ b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerRefreshTest.java
@@ -19,14 +19,20 @@ import static org.mockito.Mockito.when;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.time.Clock;
+import java.time.Instant;
 import java.time.ZoneId;
 import java.util.List;
+import java.util.stream.Stream;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jetty.client.HttpClient;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.platform.commons.support.HierarchyTraversalMode;
 import org.junit.platform.commons.support.ReflectionSupport;
 import org.mockito.Mock;
@@ -36,7 +42,7 @@ import org.mockito.quality.Strictness;
 import org.openhab.binding.awattar.internal.AwattarBindingConstants;
 import org.openhab.binding.awattar.internal.api.AwattarApi;
 import org.openhab.binding.awattar.internal.api.AwattarApi.AwattarApiException;
-import org.openhab.core.i18n.TimeZoneProvider;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.test.java.JavaTest;
 import org.openhab.core.thing.Bridge;
 import org.openhab.core.thing.Thing;
@@ -62,8 +68,9 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
     private @Mock @NonNullByDefault({}) Bridge bridgeMock;
     private @Mock @NonNullByDefault({}) ThingHandlerCallback bridgeCallbackMock;
     private @Mock @NonNullByDefault({}) HttpClient httpClientMock;
-    private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProviderMock;
+    private @Mock @NonNullByDefault({}) Clock fixedClock;
     private @Mock @NonNullByDefault({}) AwattarApi awattarApiMock;
+    private @Mock @NonNullByDefault({}) AwattarTimeProvider timeProviderMock;
 
     // best price handler mocks
     private @Mock @NonNullByDefault({}) Thing bestpriceMock;
@@ -73,10 +80,11 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
 
     @BeforeEach
     public void setUp() throws IllegalArgumentException, IllegalAccessException {
-        when(timeZoneProviderMock.getTimeZone()).thenReturn(ZoneId.of("GMT+2"));
-
         when(bridgeMock.getUID()).thenReturn(BRIDGE_UID);
-        bridgeHandler = new AwattarBridgeHandler(bridgeMock, httpClientMock, timeZoneProviderMock);
+
+        when(timeProviderMock.getZoneId()).thenReturn(ZoneId.of("GMT+2"));
+
+        bridgeHandler = new AwattarBridgeHandler(bridgeMock, httpClientMock, timeProviderMock);
         bridgeHandler.setCallback(bridgeCallbackMock);
 
         List<Field> fields = ReflectionSupport.findFields(AwattarBridgeHandler.class,
@@ -95,7 +103,7 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
      * @throws AwattarApiException
      */
     @Test
-    void testRefreshIfNeeded_ThingOffline() throws SecurityException, AwattarApiException {
+    void testRefreshIfNeededThingOffline() throws SecurityException, AwattarApiException {
         when(bridgeMock.getStatus()).thenReturn(ThingStatus.OFFLINE);
 
         bridgeHandler.refreshIfNeeded();
@@ -113,7 +121,7 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
      * @throws AwattarApiException
      */
     @Test
-    void testRefreshIfNeeded_DataEmpty() throws SecurityException, AwattarApiException {
+    void testRefreshIfNeededDataEmpty() throws SecurityException, AwattarApiException {
         when(bridgeMock.getStatus()).thenReturn(ThingStatus.ONLINE);
 
         bridgeHandler.refreshIfNeeded();
@@ -124,7 +132,7 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
     }
 
     @Test
-    void testNeedRefresh_ThingOffline() throws SecurityException {
+    void testNeedRefreshThingOffline() throws SecurityException {
         when(bridgeMock.getStatus()).thenReturn(ThingStatus.OFFLINE);
 
         // get private method via reflection
@@ -136,7 +144,7 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
     }
 
     @Test
-    void testNeedRefresh_DataEmpty() throws SecurityException, IllegalArgumentException, IllegalAccessException {
+    void testNeedRefreshDataEmpty() throws SecurityException, IllegalArgumentException, IllegalAccessException {
         when(bridgeMock.getStatus()).thenReturn(ThingStatus.ONLINE);
 
         List<Field> fields = ReflectionSupport.findFields(AwattarBridgeHandler.class,
@@ -154,4 +162,68 @@ class AwattarBridgeHandlerRefreshTest extends JavaTest {
 
         assertThat(result, is(true));
     }
+
+    public static Stream<Arguments> testNeedRefreshTimes() {
+        return Stream.of(
+                // Update at 15:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T13:00:00Z"), true),
+                Arguments.of(Instant.parse("2021-01-01T12:00:00Z"), Instant.parse("2021-01-01T13:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T13:30:00Z"), true),
+                Arguments.of(Instant.parse("2021-01-01T12:00:00Z"), Instant.parse("2021-01-01T13:30:00Z"), true),
+
+                // Update at 16:00 GMT+2 and 17:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T14:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T15:00:00Z"), false),
+
+                // Update at 18:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T16:00:00Z"), true),
+                Arguments.of(Instant.parse("2021-01-01T15:00:00Z"), Instant.parse("2021-01-01T16:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T16:30:00Z"), true),
+                Arguments.of(Instant.parse("2021-01-01T15:00:00Z"), Instant.parse("2021-01-01T16:30:00Z"), true),
+
+                // Update at 19:00 GMT+2 and 20:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T17:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T18:00:00Z"), false),
+
+                // Update at 21:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T19:00:00Z"), true),
+                Arguments.of(Instant.parse("2021-01-01T18:00:00Z"), Instant.parse("2021-01-01T19:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T19:30:00Z"), true),
+                Arguments.of(Instant.parse("2021-01-01T18:00:00Z"), Instant.parse("2021-01-01T19:30:00Z"), true),
+
+                // Update at 22:00 GMT+2, 23:00 GMT+2 and 00:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T20:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T21:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T22:00:00Z"), false),
+
+                // Update before 15:00 GMT+2
+                Arguments.of(Instant.parse("2021-01-01T11:00:00Z"), Instant.parse("2021-01-01T14:00:00Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T10:59:58Z"), Instant.parse("2021-01-01T11:59:59Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T11:59:59Z"), Instant.parse("2021-01-01T11:59:59Z"), false),
+                Arguments.of(Instant.parse("2021-01-01T13:00:00Z"), Instant.parse("2021-01-01T13:00:00Z"), false));
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void testNeedRefreshTimes(Instant lastUpdate, Instant nowUpdate, Boolean expectedResult) {
+        when(bridgeMock.getStatus()).thenReturn(ThingStatus.ONLINE);
+
+        fixedClock = Clock.fixed(lastUpdate, ZoneId.of("GMT+2"));
+        when(timeProviderMock.getZoneId()).thenReturn(fixedClock.getZone());
+        when(timeProviderMock.getInstantNow()).thenReturn(fixedClock.instant());
+
+        bridgeHandler.refreshIfNeeded();
+
+        fixedClock = Clock.fixed(nowUpdate, ZoneId.of("GMT+2"));
+        when(timeProviderMock.getZoneId()).thenReturn(fixedClock.getZone());
+        when(timeProviderMock.getInstantNow()).thenReturn(fixedClock.instant());
+        when(timeProviderMock.getZonedDateTimeNow()).thenReturn(fixedClock.instant().atZone(fixedClock.getZone()));
+
+        // get private method via reflection
+        Method method = ReflectionSupport.findMethod(AwattarBridgeHandler.class, "needRefresh", "").get();
+
+        boolean result = (boolean) ReflectionSupport.invokeMethod(method, bridgeHandler);
+
+        assertThat(result, is(expectedResult));
+    }
 }
diff --git a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerTest.java b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerTest.java
index 2a7999b83f8..a9fc5396be9 100644
--- a/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerTest.java
+++ b/bundles/org.openhab.binding.awattar/src/test/java/org/openhab/binding/awattar/internal/handler/AwattarBridgeHandlerTest.java
@@ -20,14 +20,20 @@ import static org.hamcrest.Matchers.nullValue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_ACTIVE;
+import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_COUNTDOWN;
 import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_END;
 import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_HOURS;
+import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_REMAINING;
 import static org.openhab.binding.awattar.internal.AwattarBindingConstants.CHANNEL_START;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
+import java.time.Clock;
+import java.time.Instant;
 import java.time.ZoneId;
+import java.time.ZonedDateTime;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
@@ -55,9 +61,11 @@ import org.openhab.binding.awattar.internal.AwattarPrice;
 import org.openhab.binding.awattar.internal.api.AwattarApi;
 import org.openhab.binding.awattar.internal.api.AwattarApi.AwattarApiException;
 import org.openhab.binding.awattar.internal.dto.AwattarApiData;
+import org.openhab.binding.awattar.internal.dto.AwattarTimeProvider;
 import org.openhab.core.config.core.Configuration;
-import org.openhab.core.i18n.TimeZoneProvider;
 import org.openhab.core.library.types.DateTimeType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.QuantityType;
 import org.openhab.core.library.types.StringType;
 import org.openhab.core.test.java.JavaTest;
 import org.openhab.core.thing.Bridge;
@@ -84,8 +92,8 @@ public class AwattarBridgeHandlerTest extends JavaTest {
     private @Mock @NonNullByDefault({}) Bridge bridgeMock;
     private @Mock @NonNullByDefault({}) ThingHandlerCallback bridgeCallbackMock;
     private @Mock @NonNullByDefault({}) HttpClient httpClientMock;
-    private @Mock @NonNullByDefault({}) TimeZoneProvider timeZoneProviderMock;
     private @Mock @NonNullByDefault({}) AwattarApi awattarApiMock;
+    private @Mock @NonNullByDefault({}) AwattarTimeProvider timeProviderMock;
 
     // best price handler mocks
     private @Mock @NonNullByDefault({}) Thing bestpriceMock;
@@ -109,10 +117,8 @@ public class AwattarBridgeHandlerTest extends JavaTest {
             when(awattarApiMock.getData()).thenReturn(result);
         }
 
-        when(timeZoneProviderMock.getTimeZone()).thenReturn(ZoneId.of("GMT+2"));
-
         when(bridgeMock.getUID()).thenReturn(BRIDGE_UID);
-        bridgeHandler = new AwattarBridgeHandler(bridgeMock, httpClientMock, timeZoneProviderMock);
+        bridgeHandler = new AwattarBridgeHandler(bridgeMock, httpClientMock, timeProviderMock);
         bridgeHandler.setCallback(bridgeCallbackMock);
 
         // mock the private field awattarApi
@@ -166,31 +172,105 @@ public class AwattarBridgeHandlerTest extends JavaTest {
 
     public static Stream<Arguments> testBestpriceHandler() {
         return Stream.of( //
-                Arguments.of(1, true, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
-                Arguments.of(1, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
-                Arguments.of(1, true, CHANNEL_HOURS, new StringType("14")),
-                Arguments.of(1, false, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
-                Arguments.of(1, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
-                Arguments.of(1, false, CHANNEL_HOURS, new StringType("14")),
-                Arguments.of(2, true, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
-                Arguments.of(2, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
-                Arguments.of(2, true, CHANNEL_HOURS, new StringType("13,14")),
-                Arguments.of(2, false, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
-                Arguments.of(2, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
-                Arguments.of(2, false, CHANNEL_HOURS, new StringType("13,14")));
+                Arguments.of(24, 1, true, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
+                Arguments.of(24, 1, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
+                Arguments.of(24, 1, true, CHANNEL_HOURS, new StringType("14")),
+                Arguments.of(24, 1, false, CHANNEL_START, new DateTimeType("2024-06-15T14:00:00.000+0200")),
+                Arguments.of(24, 1, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
+                Arguments.of(24, 1, false, CHANNEL_HOURS, new StringType("14")),
+                Arguments.of(24, 2, true, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
+                Arguments.of(24, 2, true, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
+                Arguments.of(24, 2, true, CHANNEL_HOURS, new StringType("13,14")),
+                Arguments.of(24, 2, false, CHANNEL_START, new DateTimeType("2024-06-15T13:00:00.000+0200")),
+                Arguments.of(24, 2, false, CHANNEL_END, new DateTimeType("2024-06-15T15:00:00.000+0200")),
+                Arguments.of(24, 2, false, CHANNEL_HOURS, new StringType("13,14")),
+                Arguments.of(34, 4, false, CHANNEL_START, new DateTimeType("2024-06-15T12:00:00.000+0200")),
+                Arguments.of(34, 4, false, CHANNEL_END, new DateTimeType("2024-06-15T16:00:00.000+0200")),
+                Arguments.of(34, 4, false, CHANNEL_HOURS, new StringType("12,13,14,15")),
+                Arguments.of(34, 8, false, CHANNEL_START, new DateTimeType("2024-06-15T12:00:00.000+0200")),
+                Arguments.of(34, 8, false, CHANNEL_END, new DateTimeType("2024-06-16T16:00:00.000+0200")),
+                Arguments.of(34, 8, false, CHANNEL_HOURS, new StringType("12,13,14,15,16,13,14,15")));
     }
 
     @ParameterizedTest
     @MethodSource
-    void testBestpriceHandler(int length, boolean consecutive, String channelId, State expectedState) {
+    void testBestpriceHandler(int rangeDuration, int length, boolean consecutive, String channelId,
+            State expectedState) {
         ThingUID bestPriceUid = new ThingUID(AwattarBindingConstants.THING_TYPE_BESTPRICE, "foo");
-        Map<String, Object> config = Map.of("length", length, "consecutive", consecutive);
+        Map<String, Object> config = Map.of("rangeDuration", rangeDuration, "length", length, "consecutive",
+                consecutive);
         when(bestpriceMock.getConfiguration()).thenReturn(new Configuration(config));
 
-        AwattarBestPriceHandler handler = new AwattarBestPriceHandler(bestpriceMock, timeZoneProviderMock) {
-            @Override
-            protected TimeRange getRange(int start, int duration, ZoneId zoneId) {
-                return new TimeRange(1718402400000L, 1718488800000L);
+        Clock clock = Clock.fixed(Instant.parse("2024-06-15T12:00:00Z"), ZoneId.of("GMT+2"));
+
+        when(timeProviderMock.getInstantNow()).thenReturn(clock.instant());
+        when(timeProviderMock.getZoneId()).thenReturn(clock.getZone());
+        when(timeProviderMock.getZonedDateTimeNow()).thenReturn(ZonedDateTime.now(clock));
+
+        AwattarBestPriceHandler handler = new AwattarBestPriceHandler(bestpriceMock, timeProviderMock) {
+            protected ZonedDateTime getStartTime(int start, ZoneId zoneId) {
+                return ZonedDateTime.of(2024, 6, 15, 12, 0, 0, 0, zoneId);
+            }
+        };
+
+        handler.setCallback(bestPriceCallbackMock);
+
+        ChannelUID channelUID = new ChannelUID(bestPriceUid, channelId);
+        handler.refreshChannel(channelUID);
+        verify(bestPriceCallbackMock).stateUpdated(channelUID, expectedState);
+    }
+
+    public static Stream<Arguments> testBestpriceHandlerChannels() {
+        return Stream.of( //
+                Arguments.of(12, 0, 24, 1, true, CHANNEL_HOURS, new StringType("14")),
+                Arguments.of(12, 0, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(false)),
+                Arguments.of(12, 0, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("120 min")),
+                Arguments.of(12, 0, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")),
+
+                Arguments.of(13, 59, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("1 min")),
+                Arguments.of(13, 59, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")),
+                Arguments.of(13, 59, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(false)),
+                Arguments.of(13, 59, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(false)),
+
+                Arguments.of(14, 01, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("0 min")),
+                Arguments.of(14, 01, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("59 min")),
+                Arguments.of(14, 01, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(true)),
+                Arguments.of(14, 01, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(true)),
+
+                Arguments.of(14, 59, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("0 min")),
+                Arguments.of(14, 59, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("1 min")),
+                Arguments.of(14, 59, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(true)),
+                Arguments.of(14, 59, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(true)),
+
+                Arguments.of(15, 00, 24, 1, true, CHANNEL_COUNTDOWN, new QuantityType<>("0 min")),
+                Arguments.of(15, 00, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")),
+                Arguments.of(15, 00, 24, 1, false, CHANNEL_ACTIVE, OnOffType.from(false)),
+                Arguments.of(15, 00, 24, 1, true, CHANNEL_ACTIVE, OnOffType.from(false)),
+
+                Arguments.of(12, 0, 24, 1, true, CHANNEL_REMAINING, new QuantityType<>("0 min")));
+    }
+
+    @ParameterizedTest
+    @MethodSource
+    void testBestpriceHandlerChannels(int currentHour, int currentMinute, int rangeDuration, int length,
+            boolean consecutive, String channelId, State expectedState) {
+        ThingUID bestPriceUid = new ThingUID(AwattarBindingConstants.THING_TYPE_BESTPRICE, "foo");
+        Map<String, Object> config = Map.of("rangeDuration", rangeDuration, "length", length, "consecutive",
+                consecutive);
+        when(bestpriceMock.getConfiguration()).thenReturn(new Configuration(config));
+
+        Clock clock = Clock.fixed(
+                ZonedDateTime.of(2024, 6, 15, currentHour, currentMinute, 0, 0, ZoneId.of("GMT+2")).toInstant(),
+                ZoneId.of("GMT+2"));
+
+        when(timeProviderMock.getInstantNow()).thenReturn(clock.instant());
+        when(timeProviderMock.getZoneId()).thenReturn(clock.getZone());
+        when(timeProviderMock.getZonedDateTimeNow())
+                .thenReturn(ZonedDateTime.ofInstant(clock.instant(), clock.getZone()));
+
+        AwattarBestPriceHandler handler = new AwattarBestPriceHandler(bestpriceMock, timeProviderMock) {
+            protected ZonedDateTime getStartTime(int start, ZoneId zoneId) {
+                return ZonedDateTime.of(2024, 6, 15, 0, 0, 0, 0, clock.getZone());
             }
         };