diff --git a/README.md b/README.md
index 9535b967e7f790ded89b86c662e0aed2daa74a12..0a06931b73e25f438e66099e3e4d5a658432a2b0 100644
--- a/README.md
+++ b/README.md
@@ -37,9 +37,55 @@ project(':amas4dc').projectDir = new File(settingsDir, '../amas4dc')
 ## Usage example 
 
 ```java
-var amas4dc = new AMAS4DC<CustomDataPoint>(new MASSettings(new CustomDataPointDistanceMethod(), 0.5f, EnumSet.noneOf(AMASOption), new CustomDataPointFuser()));
+var amas4dc = new AMAS4DC<CustomDataPoint>(new MASSettings(new CustomDataPointDistanceMethod(), 0.5f, EnumSet.noneOf(AMASOption.class), new CustomDataPointFuser()));
 
-amas4dc.fit(List.of(new CustomDataPoint(1), new CustomDataPoint(2)));
+amas4dc.fit(List.of(new CustomDataPoint(LocalDateTime.now().minusDays(1), 1.0f), new CustomDataPoint(LocalDateTime.now(), 2.0f)));
 
 var results = amas4dc.retrieveClusters();
+System.out.println("Clusters count: " + results.clusters().size());
+```
+
+```java
+public class CustomDataPoint implements DataPoint {
+	
+	private final LocalDateTime eventDateTime;
+	
+	@Getter
+	@Setter
+	private float value;
+	
+	public CustomDataPoint(LocalDateTime eventDateTime, float value) {
+		this.eventDateTime = eventDateTime;
+		this.value = value;
+	}
+	
+	@Override
+	public LocalTime getEventTime() {
+		return eventDateTime.toLocalTime();
+	}
+	
+	@Override
+	public LocalDate getEventDate() {
+		return eventDateTime.toLocalDate();
+	}
+}
+
+public class CustomDataPointFuser implements DataPointFuser<CustomDataPoint> {
+	@Override
+	public void accept(CustomDataPoint current, CustomDataPoint other) {
+		current.setValue((current.getValue() + other.getValue()) / 2);
+	}
+}
+
+public class CustomDataPointDistanceMethod implements DistanceMethod<CustomDataPoint> {
+	@Override
+	public float apply(CustomDataPoint dp1, CustomDataPoint dp2) {
+		return Math.abs(dp1.getValue() - dp2.getValue());
+	}
+
+	@Override
+	public boolean areRoughlySimilar(CustomDataPoint dp1, CustomDataPoint dp2) {
+		return true;
+	}
+}
 ```
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 67710fc0b85328b0c6993dfacde7bb4cca4c97aa..cdbea6543845ee236dab43b367351826c0c7abdc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -42,8 +42,8 @@ dependencies {
     // https://mvnrepository.com/artifact/org.projectlombok/lombok
     compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.30'
     annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.30'
-    testImplementation 'org.spockframework:spock-core:2.4-M1-groovy-4.0'
-    testImplementation 'org.codehaus.groovy:groovy-all:3.0.16'
+    testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0'
+    testImplementation 'org.codehaus.groovy:groovy-all:3.0.8'
     testImplementation 'net.bytebuddy:byte-buddy:1.14.2'
     testImplementation 'org.objenesis:objenesis:3.2'
 }
diff --git a/src/experiments/groovy/TemperatureClustering.groovy b/src/experiments/groovy/TemperatureClustering.groovy
deleted file mode 100644
index cecc709914b96648ff53ea7d34bd7982d7a27736..0000000000000000000000000000000000000000
--- a/src/experiments/groovy/TemperatureClustering.groovy
+++ /dev/null
@@ -1,187 +0,0 @@
-import fr.irit.smac.amas4dc.AMAS4DC
-import fr.irit.smac.amas4dc.amas.AMASOption
-import fr.irit.smac.amas4dc.amas.MASSettings
-import fr.irit.smac.amas4dc.cluster.Cluster
-import fr.irit.smac.amas4dc.cluster.datapoint.DataPoint
-import fr.irit.smac.amas4dc.cluster.datapoint.DataPointFuser
-import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod
-import fr.irit.smac.lxplot.LxPlot
-import groovy.transform.ToString
-
-import javax.swing.*
-import java.awt.*
-import java.util.List
-
-class TemperatureClustering {
-	static void main(String[] args) {
-
-		def amas4dc = new AMAS4DC<TemperatureDataPoint>(new MASSettings<TemperatureDataPoint>(new TemperatureDistanceMethod(),
-		                                                                                      0.5f,
-		                                                                                      EnumSet.of(AMASOption.KeepAllDataPoints),
-		                                                                                      new TemperatureDataPointFuser()))
-
-//		11 juin 2023
-//		https://www.infoclimat.fr/observations-meteo/archives/11/juin/2023/paris-montsouris/07156.html
-		def initialData = [
-				new TemperatureDataPoint(21.9, 0),
-				new TemperatureDataPoint(21.8, 1),
-				new TemperatureDataPoint(21.7, 2),
-				new TemperatureDataPoint(21.2, 3),
-				new TemperatureDataPoint(21.1, 4),
-				new TemperatureDataPoint(20.6, 5),
-				new TemperatureDataPoint(20.5, 6),
-				new TemperatureDataPoint(20.8, 7),
-				new TemperatureDataPoint(21.3, 8),
-				new TemperatureDataPoint(22.6, 9),
-				new TemperatureDataPoint(23.9, 10),
-				new TemperatureDataPoint(24.9, 11),
-				new TemperatureDataPoint(25.7, 12),
-				new TemperatureDataPoint(26.8, 13),
-				new TemperatureDataPoint(25.8, 14),
-				new TemperatureDataPoint(25.4, 15),
-				new TemperatureDataPoint(24.8, 16),
-				new TemperatureDataPoint(24.9, 17),
-				new TemperatureDataPoint(24.1, 18),
-				new TemperatureDataPoint(23.9, 19),
-				new TemperatureDataPoint(24.1, 20),
-				new TemperatureDataPoint(22.1, 21),
-				new TemperatureDataPoint(18.9, 22),
-				new TemperatureDataPoint(18.8, 23)
-		]
-
-
-		def frame = new JFrame()
-		def plotter = new Plotter()
-		frame.setContentPane(plotter)
-		frame.setSize(1400, 700)
-		frame.setVisible(true)
-
-		for (i in 0..<initialData.size()) {
-			def data = initialData.subList(i, i + 1)
-			plotter.renderInputData(initialData.subList(0, i + 1))
-			amas4dc.fit(data)
-			var results = amas4dc.retrieveExtendedClusters()
-			println(results)
-			plotter.renderClusters(results.clusters())
-			LxPlot.getChart("Silhouette distance").add(i, results.silhouetteScore())
-			sleep(1000)
-		}
-	}
-
-	@ToString
-	static class TemperatureDataPoint implements DataPoint {
-		double degrees
-		double startTime, endTime
-		double averageTime
-
-		TemperatureDataPoint(double degrees, double startTime, double endTime) {
-			this.degrees = degrees
-			this.startTime = startTime
-			this.endTime = endTime
-			this.averageTime = (startTime + endTime) / 2
-		}
-
-		TemperatureDataPoint(double degrees, double time) {
-			this(degrees, time, time)
-		}
-	}
-
-	static class TemperatureDataPointFuser implements DataPointFuser<TemperatureDataPoint> {
-
-		@Override
-		TemperatureDataPoint apply(TemperatureDataPoint dp1, TemperatureDataPoint dp2) {
-			def newStartTime = dp1.startTime
-			def newEndTime = dp1.endTime
-			if (dp2.startTime < newStartTime)
-				newStartTime = dp2.startTime
-			if (dp2.endTime > newEndTime)
-				newEndTime = dp2.endTime
-			return new TemperatureDataPoint(dp1.degrees * 0.9 + dp2.degrees * 0.1, newStartTime, newEndTime)
-		}
-	}
-
-	static class TemperatureDistanceMethod implements DistanceMethod<TemperatureDataPoint> {
-
-		@Override
-		float apply(TemperatureDataPoint dp1, TemperatureDataPoint dp2) {
-			var temporallySimilar = false
-			if (dp1.endTime < dp2.startTime) {
-				if (dp2.startTime - dp1.endTime < 2)
-					temporallySimilar = true
-				else
-					temporallySimilar = false
-			} else if (dp2.endTime < dp1.startTime) {
-				if (dp1.startTime - dp2.endTime < 2)
-					temporallySimilar = true
-				else
-					temporallySimilar = false
-			}
-			if (Math.abs(dp1.degrees - dp2.degrees) < 1 && temporallySimilar)
-				return 0;
-			return 1;
-		}
-
-		@Override
-		boolean areRoughlySimilar(TemperatureDataPoint dp1, TemperatureDataPoint dp2) {
-			return true
-		}
-	}
-
-	static class Plotter extends JPanel {
-		ArrayList<TemperatureDataPoint> inputData
-		List<Cluster<TemperatureDataPoint>> clusters
-		Map<String, Color> clustersColors = new HashMap<>()
-
-		@Override
-		protected void paintComponent(Graphics g) {
-			var g2d = (Graphics2D) g
-
-			if (inputData == null)
-				return
-			g2d.setColor(Color.white)
-			g2d.fillRect(0, 0, 1400, 700)
-			g2d.setColor(Color.BLACK)
-			g2d.drawLine(timeToX(0), degreeToY(0), timeToX(24), degreeToY(0))
-			g2d.drawLine(timeToX(0), degreeToY(0), timeToX(0), degreeToY(30))
-
-			for (def tdp : inputData) {
-				g2d.drawOval(timeToX(tdp.startTime) - 3, degreeToY(tdp.degrees) - 3, 6, 6)
-			}
-			def random = new Random()
-			for (def c : clusters) {
-				def color = clustersColors.computeIfAbsent(c.id, id -> new Color(random.nextFloat(), random.nextFloat(), random.nextFloat()))
-				g2d.setColor(Color.BLUE)
-				g2d.setStroke(new BasicStroke(2))
-				g2d.drawLine(timeToX(c.representative.startTime), degreeToY(c.representative.degrees), timeToX(c.representative.endTime), degreeToY(c.representative.degrees))
-			}
-			g2d.setColor(Color.BLACK)
-			for (i in 0..<24) {
-				g2d.drawString(i + "", timeToX(i), 665)
-			}
-			g2d.drawString("Hour of the day", timeToX(24), 665)
-			for (i in 0..<30) {
-				g2d.drawString(i + "", 10, degreeToY(i))
-			}
-			g2d.drawString("Temperature °C", 10, degreeToY(30))
-
-		}
-
-		int timeToX(double time) {
-			return (int) (time * 40) + 50
-		}
-
-		int degreeToY(double degree) {
-			return 650 - (int) (degree * 20)
-		}
-
-		void renderInputData(List<TemperatureDataPoint> inputDataList) {
-			this.inputData = inputDataList
-			repaint();
-		}
-
-		void renderClusters(List<Cluster<TemperatureDataPoint>> clusters) {
-			this.clusters = clusters
-			repaint()
-		}
-	}
-}
diff --git a/src/experiments/groovy/TwoDimensionsPointsClustering.groovy b/src/experiments/groovy/TwoDimensionsPointsClustering.groovy
index 79eb2e4fd4ed793876ead340478e49044820bd36..0d39d86fa168bfa00be4064c1f3d3bc48554f6ef 100644
--- a/src/experiments/groovy/TwoDimensionsPointsClustering.groovy
+++ b/src/experiments/groovy/TwoDimensionsPointsClustering.groovy
@@ -9,6 +9,9 @@ import fr.irit.smac.lxplot.commons.ChartType
 import groovy.transform.ToString
 
 import java.awt.geom.Point2D
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.LocalTime
 
 class TwoDimensionsPointsClustering {
 	static void main(String[] args) {
@@ -42,9 +45,20 @@ class TwoDimensionsPointsClustering {
 	@ToString
 	static class TwoDimensionsDataPoint implements DataPoint {
 		Point2D.Double point2D
+		LocalDateTime time
 
 		TwoDimensionsDataPoint(Point2D.Double point2D) {
 			this.point2D = point2D
+			this.time = LocalDateTime.now()
+		}
+		@Override
+		LocalTime getEventTime() {
+			return this.time.toLocalTime()
+		}
+
+		@Override
+		LocalDate getEventDate() {
+			return this.time.toLocalDate()
 		}
 	}
 
diff --git a/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java b/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java
index 4f5a81444ca12952c3e872622f8fd70b2ba7fe84..ae4f05187062abd5c4320a72947bc2b4643ba568 100644
--- a/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java
+++ b/src/main/java/fr/irit/smac/amas4dc/amas/agent/ClusterAgent.java
@@ -164,7 +164,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 		if (logger.isLoggable(Level.INFO))
 			logger.info(this + " absorbs the data point " + otherDataPoint);
 
-		amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherDataPoint);
+		amas.getMasSettings().dataPointFuser().accept(cluster.getRepresentative(), otherDataPoint);
 		cluster.addDataPoint(otherDataPoint);
 	}
 
@@ -172,7 +172,7 @@ public class ClusterAgent<T extends DataPoint> extends Agent<DynamicClusteringAM
 		if (logger.isLoggable(Level.INFO))
 			logger.info(this + " absorbs the cluster " + otherCluster);
 
-		amas.getMasSettings().dataPointFuser().apply(cluster.getRepresentative(), otherCluster.getRepresentative());
+		amas.getMasSettings().dataPointFuser().accept(cluster.getRepresentative(), otherCluster.getRepresentative());
 
 		if (getAmas().getMasSettings().amasOptions().contains(AMASOption.KeepAllDataPoints))
 			((ExtendedCluster<T>) cluster).addClusterContent((ExtendedCluster<T>) otherCluster);
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java
index 5199f76ac98d5a21f56baead8cdbf2c940f2e9c8..f32c5829b76fbdb2911835a05456261f675173d8 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPoint.java
@@ -1,7 +1,14 @@
 package fr.irit.smac.amas4dc.cluster.datapoint;
 
+import java.time.LocalDate;
+import java.time.LocalTime;
+
 public interface DataPoint {
 	default int getBucketId() {
 		return 0;
 	}
+
+	LocalTime getEventTime();
+
+	LocalDate getEventDate();
 }
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java
index 90788b8c67befe4e4b876079db8e430ece841400..cc3ea7975de30a06ad293451302d3f6edd03725a 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/datapoint/DataPointFuser.java
@@ -1,6 +1,7 @@
 package fr.irit.smac.amas4dc.cluster.datapoint;
 
+import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 
-public interface DataPointFuser<T extends DataPoint> extends BiFunction<T, T, T> {
+public interface DataPointFuser<T extends DataPoint> extends BiConsumer<T, T> {
 }
diff --git a/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java b/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java
index 9c95f335fa6ec29ff41bf300b7abeeb9cb8a9518..d2826f58e76fb41a2e5fed7683548d466dbbf524 100644
--- a/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java
+++ b/src/main/java/fr/irit/smac/amas4dc/cluster/evaluation/CalinskiHarabazIndex.java
@@ -52,7 +52,7 @@ public class CalinskiHarabazIndex<T extends DataPoint> {
 	private T computeGlobalCentroid(List<ExtendedCluster<T>> clusters, MASSettings<T> masSettings) {
 		var fused = clusters.get(0).getRepresentative();
 		for (int i = 1; i < clusters.size(); i++) {
-			fused = masSettings.dataPointFuser().apply(fused, clusters.get(i).getRepresentative());
+			masSettings.dataPointFuser().accept(fused, clusters.get(i).getRepresentative());
 		}
 		return fused;
 	}
diff --git a/src/test/groovy/SimpleClusteringIT.groovy b/src/test/groovy/SimpleClusteringIT.groovy
index fdbd112fef20fa48427e0e71235a12eaf328ff3c..57d39ef375d89e2970e0dcaf36a7919cde92a8fe 100644
--- a/src/test/groovy/SimpleClusteringIT.groovy
+++ b/src/test/groovy/SimpleClusteringIT.groovy
@@ -6,6 +6,10 @@ import fr.irit.smac.amas4dc.cluster.datapoint.DataPointDatabase
 import fr.irit.smac.amas4dc.cluster.distance.DistanceMethod
 import spock.lang.Specification
 
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.LocalTime
+
 class SimpleClusteringIT extends Specification {
 	def "Clustering of two similar 1D objects"() {
 		def database = new DataPointDatabase<OneDDataPoint>()
@@ -25,10 +29,22 @@ class SimpleClusteringIT extends Specification {
 	}
 
 	class OneDDataPoint implements DataPoint {
-		public final double value
+		private final double value
+		private final LocalDateTime time
 
 		OneDDataPoint(double value) {
-			this.value = value;
+			this.value = value
+			this.time = LocalDateTime.now()
+		}
+
+		@Override
+		LocalTime getEventTime() {
+			return this.time.toLocalTime()
+		}
+
+		@Override
+		LocalDate getEventDate() {
+			return this.time.toLocalDate()
 		}
 	}