|
4 | 4 | import java.lang.reflect.Field;
|
5 | 5 | import java.math.BigDecimal;
|
6 | 6 | import java.math.BigInteger;
|
| 7 | +import java.math.RoundingMode; |
7 | 8 | import java.text.NumberFormat;
|
8 | 9 | import java.time.Instant;
|
9 | 10 | import java.util.Locale;
|
|
28 | 29 | public class Point {
|
29 | 30 | private String measurement;
|
30 | 31 | private Map<String, String> tags;
|
31 |
| - private Long time; |
| 32 | + private Number time; |
32 | 33 | private TimeUnit precision = TimeUnit.NANOSECONDS;
|
33 | 34 | private Map<String, Object> fields;
|
34 | 35 | private static final int MAX_FRACTION_DIGITS = 340;
|
@@ -89,9 +90,10 @@ private static void throwExceptionIfMissingAnnotation(final Class<?> clazz,
|
89 | 90 | *
|
90 | 91 | */
|
91 | 92 | public static final class Builder {
|
| 93 | + private static final BigInteger NANOSECONDS_PER_SECOND = BigInteger.valueOf(1000000000L); |
92 | 94 | private final String measurement;
|
93 | 95 | private final Map<String, String> tags = new TreeMap<>();
|
94 |
| - private Long time; |
| 96 | + private Number time; |
95 | 97 | private TimeUnit precision;
|
96 | 98 | private final Map<String, Object> fields = new TreeMap<>();
|
97 | 99 |
|
@@ -220,17 +222,30 @@ public Builder fields(final Map<String, Object> fieldsToAdd) {
|
220 | 222 | /**
|
221 | 223 | * Add a time to this point.
|
222 | 224 | *
|
223 |
| - * @param timeToSet the time for this point |
| 225 | + * @param timeToSet the time for this point |
224 | 226 | * @param precisionToSet the TimeUnit
|
225 | 227 | * @return the Builder instance.
|
226 | 228 | */
|
227 |
| - public Builder time(final long timeToSet, final TimeUnit precisionToSet) { |
| 229 | + public Builder time(final Number timeToSet, final TimeUnit precisionToSet) { |
| 230 | + Objects.requireNonNull(timeToSet, "timeToSet"); |
228 | 231 | Objects.requireNonNull(precisionToSet, "precisionToSet");
|
229 | 232 | this.time = timeToSet;
|
230 | 233 | this.precision = precisionToSet;
|
231 | 234 | return this;
|
232 | 235 | }
|
233 | 236 |
|
| 237 | + /** |
| 238 | + * Add a time to this point as Long. |
| 239 | + * only kept for binary compatibility with previous releases. |
| 240 | + * |
| 241 | + * @param timeToSet the time for this point as Long |
| 242 | + * @param precisionToSet the TimeUnit |
| 243 | + * @return the Builder instance. |
| 244 | + */ |
| 245 | + public Builder time(final Long timeToSet, final TimeUnit precisionToSet) { |
| 246 | + return time((Number) timeToSet, precisionToSet); |
| 247 | + } |
| 248 | + |
234 | 249 | /**
|
235 | 250 | * Does this builder contain any fields?
|
236 | 251 | *
|
@@ -283,9 +298,17 @@ private void addFieldByAttribute(final Object pojo, final Field field, final Col
|
283 | 298 | TimeColumn tc = field.getAnnotation(TimeColumn.class);
|
284 | 299 | if (tc != null && Instant.class.isAssignableFrom(field.getType())) {
|
285 | 300 | Optional.ofNullable((Instant) fieldValue).ifPresent(instant -> {
|
286 |
| - TimeUnit timeUint = tc.timeUnit(); |
287 |
| - this.time = TimeUnit.MILLISECONDS.convert(instant.toEpochMilli(), timeUint); |
288 |
| - this.precision = timeUint; |
| 301 | + TimeUnit timeUnit = tc.timeUnit(); |
| 302 | + if (timeUnit == TimeUnit.NANOSECONDS || timeUnit == TimeUnit.MICROSECONDS) { |
| 303 | + this.time = BigInteger.valueOf(instant.getEpochSecond()) |
| 304 | + .multiply(NANOSECONDS_PER_SECOND) |
| 305 | + .add(BigInteger.valueOf(instant.getNano())) |
| 306 | + .divide(BigInteger.valueOf(TimeUnit.NANOSECONDS.convert(1, timeUnit))); |
| 307 | + } else { |
| 308 | + this.time = TimeUnit.MILLISECONDS.convert(instant.toEpochMilli(), timeUnit); |
| 309 | + this.precision = timeUnit; |
| 310 | + } |
| 311 | + this.precision = timeUnit; |
289 | 312 | });
|
290 | 313 | return;
|
291 | 314 | }
|
@@ -339,7 +362,7 @@ void setMeasurement(final String measurement) {
|
339 | 362 | * @param time
|
340 | 363 | * the time to set
|
341 | 364 | */
|
342 |
| - void setTime(final Long time) { |
| 365 | + void setTime(final Number time) { |
343 | 366 | this.time = time;
|
344 | 367 | }
|
345 | 368 |
|
@@ -553,13 +576,37 @@ private void formatedTime(final StringBuilder sb, final TimeUnit precision) {
|
553 | 576 | if (this.time == null) {
|
554 | 577 | return;
|
555 | 578 | }
|
556 |
| - if (precision == null) { |
557 |
| - sb.append(" ").append(TimeUnit.NANOSECONDS.convert(this.time, this.precision)); |
558 |
| - return; |
| 579 | + TimeUnit converterPrecision = precision; |
| 580 | + |
| 581 | + if (converterPrecision == null) { |
| 582 | + converterPrecision = TimeUnit.NANOSECONDS; |
| 583 | + } |
| 584 | + if (this.time instanceof BigInteger) { |
| 585 | + BigInteger time = (BigInteger) this.time; |
| 586 | + long conversionFactor = converterPrecision.convert(1, this.precision); |
| 587 | + if (conversionFactor >= 1) { |
| 588 | + time = time.multiply(BigInteger.valueOf(conversionFactor)); |
| 589 | + } else { |
| 590 | + conversionFactor = this.precision.convert(1, converterPrecision); |
| 591 | + time = time.divide(BigInteger.valueOf(conversionFactor)); |
| 592 | + } |
| 593 | + sb.append(" ").append(time); |
| 594 | + } else if (this.time instanceof BigDecimal) { |
| 595 | + BigDecimal time = (BigDecimal) this.time; |
| 596 | + long conversionFactor = converterPrecision.convert(1, this.precision); |
| 597 | + if (conversionFactor >= 1) { |
| 598 | + time = time.multiply(BigDecimal.valueOf(conversionFactor)); |
| 599 | + } else { |
| 600 | + conversionFactor = this.precision.convert(1, converterPrecision); |
| 601 | + time = time.divide(BigDecimal.valueOf(conversionFactor), RoundingMode.HALF_UP); |
| 602 | + } |
| 603 | + sb.append(" ").append(time.toBigInteger()); |
| 604 | + } else { |
| 605 | + sb.append(" ").append(converterPrecision.convert(this.time.longValue(), this.precision)); |
559 | 606 | }
|
560 |
| - sb.append(" ").append(precision.convert(this.time, this.precision)); |
561 | 607 | }
|
562 | 608 |
|
| 609 | + |
563 | 610 | private static String findMeasurementName(final Class<?> clazz) {
|
564 | 611 | return clazz.getAnnotation(Measurement.class).name();
|
565 | 612 | }
|
|
0 commit comments