package com.linkedin.thirdeye.api;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import org.joda.time.Period;
import com.fasterxml.jackson.annotation.JsonProperty;
public class TimeGranularity {
private final int size;
private final TimeUnit unit;
public TimeGranularity() {
this(1, TimeUnit.HOURS);
}
public TimeGranularity(int size, TimeUnit unit) {
this.size = size;
this.unit = unit;
}
/**
* Copy constructor
* @param that to be copied
*/
public TimeGranularity(TimeGranularity that) {
this(that.getSize(), that.getUnit());
}
@JsonProperty
public int getSize() {
return size;
}
@JsonProperty
public TimeUnit getUnit() {
return unit;
}
/**
* Returns the equivalent milliseconds of this time granularity.
*
* @return the equivalent milliseconds of this time granularity.
*/
public long toMillis() {
return toMillis(1);
}
/**
* Returns the equivalent milliseconds of the specified number of this time granularity. Highly suggested to use
* toPeriod instead of this method for handling daylight saving time issue.
*
* @param number the specified number of this time granularity.
*
* @return the equivalent milliseconds of the specified number of this time granularity.
*/
public long toMillis(long number) {
return unit.toMillis(number * size);
}
/**
* Returns an equivalent Period object of this time granularity.
*
* @return an equivalent Period object of this time granularity.
*/
public Period toPeriod() {
return toPeriod(1);
}
/**
* Returns an equivalent Period object of the specified number of this time granularity.
*
* @param number the specified number of this time granularity.
*
* @return an equivalent Period object of the specified number of this time granularity.
*/
public Period toPeriod(int number) {
int size = this.size * number;
switch (unit) {
case DAYS:
return new Period(0, 0, 0, size, 0, 0, 0, 0);
case HOURS:
return new Period(0, 0, 0, 0, size, 0, 0, 0);
case MINUTES:
return new Period(0, 0, 0, 0, 0, size, 0, 0);
case SECONDS:
return new Period(0, 0, 0, 0, 0, 0, size, 0);
case MILLISECONDS:
return new Period(0, 0, 0, 0, 0, 0, 0, size);
default:
return new Period(0, 0, 0, 0, size, 0, 0, 0);
}
}
/**
* Converts millis to time unit
* e.g. If TimeGranularity is defined as 1 HOURS,
* and we invoke convertToUnit(1458284400000) (i.e. 2016-03-18 00:00:00)
* this method will return HOURS.convert(1458284400000, MILLISECONDS)/1 = 405079 hoursSinceEpoch
* If TimeGranularity is defined as 10 MINUTES,
* and we invoke convertToUnit(1458284400000) (i.e. 2016-03-18 00:00:00)
* this method will return MINUTES.convert(1458284400000, MILLISECONDS)/10 = 2430474
* tenMinutesSinceEpoch
* @param millis
* @return
*/
public long convertToUnit(long millis) {
return unit.convert(millis, TimeUnit.MILLISECONDS) / size;
}
/**
* Initialize time granularity from its aggregation string representation, in which duration and unit are separated
* by "_". For instance, "5_MINUTES" initialize a time granularity with size = 5 and TimeUnit = "MINUTES".
*
* @param timeGranularityString the aggregation string representation of the time granularity.
*
* @return time granularity that is initialized from the given aggregation string representation.
*/
public static TimeGranularity fromString(String timeGranularityString) {
if (timeGranularityString.contains("_")) {
String[] split = timeGranularityString.split("_");
return new TimeGranularity(Integer.parseInt(split[0]), TimeUnit.valueOf(split[1]));
} else {
return new TimeGranularity(1, TimeUnit.valueOf(timeGranularityString));
}
}
/**
* Return the string representation of this time granularity, in which duration and unit are separated by "_".
*
* @return the string representation of this time granularity, in which duration and unit are separated by "_".
*/
public String toAggregationGranularityString() {
return size + "_" + unit;
}
/**
* Return the string representation of this time granularity, in which duration and unit are separated by "-".
*
* @return the string representation of this time granularity, in which duration and unit are separated by "-".
*/
@Override
public String toString() {
return size + "-" + unit;
}
@Override
public int hashCode() {
return Objects.hash(size, unit);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TimeGranularity)) {
return false;
}
TimeGranularity other = (TimeGranularity) obj;
return Objects.equals(other.size, this.size) && Objects.equals(other.unit, this.unit);
}
}