Skip to content

Commit

Permalink
Switch TimeSeries to nanosecond precision (#3281)
Browse files Browse the repository at this point in the history
* switch to nanosecond precision
* add Javadoc
* add new enum TimeSeriesIndex.ExportFormat
* fix ser/de via strings and BigInteger to avoid overflows

Signed-off-by: Nicolas Rol <[email protected]>
  • Loading branch information
rolnico authored Feb 11, 2025
1 parent 3198386 commit 1d22961
Show file tree
Hide file tree
Showing 35 changed files with 1,016 additions and 322 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -43,7 +45,7 @@ public String getStatusText() {

@Override
public Map<String, DoubleTimeSeries> getCurves() {
return Collections.singletonMap("curve1", TimeSeries.createDouble("curve1", new RegularTimeSeriesIndex(0, 5, 1), 0.0, 0.1, 0.1, 0.2, 0.1, 0.0));
return Collections.singletonMap("curve1", TimeSeries.createDouble("curve1", new RegularTimeSeriesIndex(Instant.ofEpochMilli(0), Instant.ofEpochMilli(5), Duration.ofMillis(1)), 0.0, 0.1, 0.1, 0.2, 0.1, 0.0));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,38 @@
*/
package com.powsybl.timeseries;

import java.time.Instant;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public abstract class AbstractPoint {

protected final int index;

protected final long time;
protected final Instant instant;

protected AbstractPoint(int index, long time) {
protected AbstractPoint(int index, Instant instant) {
if (index < 0) {
throw new IllegalArgumentException("Bad index value " + index);
}
this.index = index;
this.time = time;
this.instant = instant;
}

public int getIndex() {
return index;
}

/**
* @deprecated Replaced by {@link #getInstant()}
*/
@Deprecated(since = "6.7.0")
public long getTime() {
return time;
return instant.toEpochMilli();
}

public Instant getInstant() {
return instant;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,35 @@
*/
package com.powsybl.timeseries;

import com.fasterxml.jackson.core.JsonGenerator;
import com.powsybl.commons.json.JsonUtil;

import java.time.Instant;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public abstract class AbstractTimeSeriesIndex implements TimeSeriesIndex {

/**
* @deprecated Replaced by {@link #getInstantAt(int)}}
*/
@Deprecated(since = "6.7.0")
@Override
public Instant getInstantAt(int point) {
return Instant.ofEpochMilli(getTimeAt(point));
public long getTimeAt(int point) {
return getInstantAt(point).toEpochMilli();
}

@Override
public String toJson() {
return JsonUtil.toJson(this::writeJson);
return toJson(ExportFormat.MILLISECONDS);
}

@Override
public String toJson(ExportFormat format) {
return JsonUtil.toJson(generator -> this.writeJson(generator, format));
}

@Override
public void writeJson(JsonGenerator generator) {
writeJson(generator, ExportFormat.MILLISECONDS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public void synchronize(TimeSeriesIndex newIndex) {
}

//To remove if we ever get it from somewhere else
@FunctionalInterface private interface DoubleIntConsumer { public void accept(double a, int b); }
@FunctionalInterface private interface DoubleIntConsumer { void accept(double a, int b); }

private void forEachMaterializedValueIndex(DoubleIntConsumer consumer) {
if (metadata.getIndex() == InfiniteTimeSeriesIndex.INSTANCE) {
Expand Down Expand Up @@ -218,12 +218,12 @@ public TimeSeriesIndex getIndex() {

private static DoublePoint evaluateMultiPoint(NodeCalc resolvedNodeCalc, DoubleMultiPoint multiPoint) {
double value = NodeCalcEvaluator.eval(resolvedNodeCalc, multiPoint);
return new DoublePoint(multiPoint.getIndex(), multiPoint.getTime(), value);
return new DoublePoint(multiPoint.getIndex(), multiPoint.getInstant(), value);
}

private static DoublePoint evaluate(NodeCalc resolvedNodeCalc) {
double value = NodeCalcEvaluator.eval(resolvedNodeCalc, null);
return new DoublePoint(0, InfiniteTimeSeriesIndex.START_TIME, value);
return new DoublePoint(0, InfiniteTimeSeriesIndex.START_INSTANT, value);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public DoublePoint next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
DoublePoint point = new DoublePoint(i, index.getTimeAt(i), stepValues[step]);
DoublePoint point = new DoublePoint(i, index.getInstantAt(i), stepValues[step]);
i += stepLengths[step];
step++;
return point;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public StringPoint next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
StringPoint point = new StringPoint(i, index.getTimeAt(i), stepValues[step]);
StringPoint point = new StringPoint(i, index.getInstantAt(i), stepValues[step]);
i += stepLengths[step];
step++;
return point;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/
package com.powsybl.timeseries;

import java.time.Instant;

/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
Expand All @@ -16,5 +18,7 @@ public interface DoubleMultiPoint {

long getTime();

Instant getInstant();

double getValue(int timeSeriesNum);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@ public class DoublePoint extends AbstractPoint {

private final double value;

/**
* @deprecated Replaced by {@link #DoublePoint(int, Instant, double)}
*/
@Deprecated(since = "6.7.0")
public DoublePoint(int index, long time, double value) {
super(index, time);
this(index, Instant.ofEpochMilli(time), value);
}

public DoublePoint(int index, Instant instant, double value) {
super(index, instant);
this.value = value;
}

Expand All @@ -28,13 +36,13 @@ public double getValue() {

@Override
public int hashCode() {
return Objects.hash(index, time, value);
return Objects.hash(index, instant, value);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof DoublePoint other) {
return index == other.index && time == other.time
return index == other.index && instant.equals(other.instant)
&& (Double.isNaN(value) && Double.isNaN(other.value)
|| value == other.value);
}
Expand All @@ -43,6 +51,6 @@ public boolean equals(Object obj) {

@Override
public String toString() {
return "DoublePoint(index=" + index + ", time=" + Instant.ofEpochMilli(time) + ", value=" + value + ")";
return "DoublePoint(index=" + index + ", instant=" + instant + ", value=" + value + ")";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
package com.powsybl.timeseries;

import java.nio.DoubleBuffer;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
Expand Down Expand Up @@ -99,7 +100,12 @@ public int getIndex() {

@Override
public long getTime() {
return e.getValue().get(0).getPoint().getTime();
return getInstant().toEpochMilli();
}

@Override
public Instant getInstant() {
return e.getValue().get(0).getPoint().getInstant();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,29 @@ public class InfiniteTimeSeriesIndex extends AbstractTimeSeriesIndex {
public static final InfiniteTimeSeriesIndex INSTANCE = new InfiniteTimeSeriesIndex();

public static final String TYPE = "infiniteIndex";
public static final long START_TIME = 0L;
public static final long END_TIME = Long.MAX_VALUE;
public static final Instant START_INSTANT = Instant.ofEpochMilli(0L);
public static final Instant END_INSTANT = Instant.ofEpochMilli(Long.MAX_VALUE);

@Override
public int getPointCount() {
return 2;
}

/**
* @deprecated Replaced by {@link #getInstantAt(int)}}
*/
@Deprecated(since = "6.7.0")
@Override
public long getTimeAt(int point) {
return getInstantAt(point).toEpochMilli();
}

@Override
public Instant getInstantAt(int point) {
if (point == 0) {
return START_TIME;
return START_INSTANT;
} else if (point == 1) {
return END_TIME;
return END_INSTANT;
} else {
throw new TimeSeriesException("Point " + point + " not found");
}
Expand All @@ -52,7 +61,7 @@ public String getType() {
}

@Override
public void writeJson(JsonGenerator generator) {
public void writeJson(JsonGenerator generator, ExportFormat timeFormat) {
Objects.requireNonNull(generator);
try {
generator.writeStartObject();
Expand All @@ -79,12 +88,12 @@ public static InfiniteTimeSeriesIndex parseJson(JsonParser parser) {

@Override
public Iterator<Instant> iterator() {
return Arrays.asList(Instant.ofEpochMilli(START_TIME), Instant.ofEpochMilli(END_TIME)).iterator();
return Arrays.asList(START_INSTANT, END_INSTANT).iterator();
}

@Override
public Stream<Instant> stream() {
return Stream.of(Instant.ofEpochMilli(START_TIME), Instant.ofEpochMilli(END_TIME));
return Stream.of(START_INSTANT, END_INSTANT);
}

@Override
Expand Down
Loading

0 comments on commit 1d22961

Please sign in to comment.