committed by
GitHub
37 changed files with 1007 additions and 316 deletions
@ -0,0 +1,92 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
package org.thingsboard.server.common.data.kv; |
||||
|
|
||||
|
import lombok.AllArgsConstructor; |
||||
|
import lombok.EqualsAndHashCode; |
||||
|
import lombok.Getter; |
||||
|
import lombok.extern.slf4j.Slf4j; |
||||
|
import org.thingsboard.server.common.data.StringUtils; |
||||
|
|
||||
|
import java.time.DateTimeException; |
||||
|
import java.time.ZoneId; |
||||
|
import java.util.Map; |
||||
|
import java.util.concurrent.TimeUnit; |
||||
|
|
||||
|
@AllArgsConstructor |
||||
|
@EqualsAndHashCode |
||||
|
@Slf4j |
||||
|
public class AggregationParams { |
||||
|
private static final Map<String, String> TZ_LINKS = Map.of("EST", "America/New_York", "GMT+0", "GMT", "GMT-0", "GMT", "HST", "US/Hawaii", "MST", "America/Phoenix", "ROC", "Asia/Taipei"); |
||||
|
@Getter |
||||
|
private final Aggregation aggregation; |
||||
|
@Getter |
||||
|
private final IntervalType intervalType; |
||||
|
@Getter |
||||
|
private final ZoneId tzId; |
||||
|
|
||||
|
private final long interval; |
||||
|
|
||||
|
public static AggregationParams none() { |
||||
|
return new AggregationParams(Aggregation.NONE, null, null, 0L); |
||||
|
} |
||||
|
|
||||
|
public static AggregationParams milliseconds(Aggregation aggregationType, long aggregationIntervalMs) { |
||||
|
return new AggregationParams(aggregationType, IntervalType.MILLISECONDS, null, aggregationIntervalMs); |
||||
|
} |
||||
|
|
||||
|
public static AggregationParams calendar(Aggregation aggregationType, IntervalType intervalType, String tzIdStr) { |
||||
|
return calendar(aggregationType, intervalType, getZoneId(tzIdStr)); |
||||
|
} |
||||
|
|
||||
|
public static AggregationParams calendar(Aggregation aggregationType, IntervalType intervalType, ZoneId tzId) { |
||||
|
return new AggregationParams(aggregationType, intervalType, tzId, 0L); |
||||
|
} |
||||
|
|
||||
|
public static AggregationParams of(Aggregation aggregation, IntervalType intervalType, ZoneId tzId, long interval) { |
||||
|
return new AggregationParams(aggregation, intervalType, tzId, interval); |
||||
|
} |
||||
|
|
||||
|
public long getInterval() { |
||||
|
if (intervalType == null) { |
||||
|
return 0L; |
||||
|
} else { |
||||
|
switch (intervalType) { |
||||
|
case WEEK: |
||||
|
case WEEK_ISO: |
||||
|
return TimeUnit.DAYS.toMillis(7); |
||||
|
case MONTH: |
||||
|
return TimeUnit.DAYS.toMillis(30); |
||||
|
case QUARTER: |
||||
|
return TimeUnit.DAYS.toMillis(90); |
||||
|
default: |
||||
|
return interval; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static ZoneId getZoneId(String tzIdStr) { |
||||
|
if (StringUtils.isEmpty(tzIdStr)) { |
||||
|
return ZoneId.systemDefault(); |
||||
|
} |
||||
|
try { |
||||
|
return ZoneId.of(tzIdStr, TZ_LINKS); |
||||
|
} catch (DateTimeException e) { |
||||
|
log.warn("[{}] Failed to convert the time zone. Fallback to default.", tzIdStr); |
||||
|
return ZoneId.systemDefault(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
package org.thingsboard.server.common.data.kv; |
||||
|
|
||||
|
public enum IntervalType { |
||||
|
|
||||
|
MILLISECONDS, WEEK/*Sunday-Saturday*/, WEEK_ISO/*Monday-Sunday*/, MONTH, QUARTER |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
package org.thingsboard.server.dao.util; |
||||
|
|
||||
|
import org.thingsboard.server.common.data.kv.IntervalType; |
||||
|
|
||||
|
import java.time.Instant; |
||||
|
import java.time.ZoneId; |
||||
|
import java.time.ZonedDateTime; |
||||
|
import java.time.temporal.ChronoUnit; |
||||
|
import java.time.temporal.IsoFields; |
||||
|
import java.time.temporal.WeekFields; |
||||
|
|
||||
|
public class TimeUtils { |
||||
|
|
||||
|
public static long calculateIntervalEnd(long startTs, IntervalType intervalType, ZoneId tzId) { |
||||
|
var startTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(startTs), tzId); |
||||
|
switch (intervalType) { |
||||
|
case WEEK: |
||||
|
return startTime.truncatedTo(ChronoUnit.DAYS).with(WeekFields.SUNDAY_START.dayOfWeek(), 1).plusDays(7).toInstant().toEpochMilli(); |
||||
|
case WEEK_ISO: |
||||
|
return startTime.truncatedTo(ChronoUnit.DAYS).with(WeekFields.ISO.dayOfWeek(), 1).plusDays(7).toInstant().toEpochMilli(); |
||||
|
case MONTH: |
||||
|
return startTime.truncatedTo(ChronoUnit.DAYS).withDayOfMonth(1).plusMonths(1).toInstant().toEpochMilli(); |
||||
|
case QUARTER: |
||||
|
return startTime.truncatedTo(ChronoUnit.DAYS).with(IsoFields.DAY_OF_QUARTER, 1).plusMonths(3).toInstant().toEpochMilli(); |
||||
|
default: |
||||
|
throw new RuntimeException("Not supported!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2024 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
package org.thingsboard.server.dao.util; |
||||
|
|
||||
|
import org.junit.jupiter.api.Test; |
||||
|
import org.thingsboard.server.common.data.kv.IntervalType; |
||||
|
|
||||
|
import java.time.ZoneId; |
||||
|
|
||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
|
||||
|
class TimeUtilsTest { |
||||
|
|
||||
|
@Test |
||||
|
void testWeekEnd() { |
||||
|
long ts = 1704899727000L; // Wednesday, January 10 15:15:27 GMT
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.WEEK, ZoneId.of("Europe/Kyiv"))).isEqualTo(1705183200000L); // Sunday, January 14, 2024 0:00:00 GMT+02:00
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.WEEK_ISO, ZoneId.of("Europe/Kyiv"))).isEqualTo(1705269600000L); // Monday, January 15, 2024 0:00:00 GMT+02:00
|
||||
|
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.WEEK, ZoneId.of("Europe/Amsterdam"))).isEqualTo(1705186800000L); // Sunday, January 14, 2024 0:00:00 GMT+01:00
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.WEEK_ISO, ZoneId.of("Europe/Amsterdam"))).isEqualTo(1705273200000L); // Monday, January 15, 2024 0:00:00 GMT+01:00
|
||||
|
|
||||
|
ts = 1704621600000L; // Sunday, January 7, 2024 12:00:00 GMT+02:00
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.WEEK, ZoneId.of("Europe/Kyiv"))).isEqualTo(1705183200000L); // Sunday, January 14, 2024 0:00:00 GMT+02:00
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.WEEK_ISO, ZoneId.of("Europe/Kyiv"))).isEqualTo(1704664800000L); // Monday, January 8, 2024 0:00:00 GMT+02:00
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
@Test |
||||
|
void testMonthEnd() { |
||||
|
long ts = 1704899727000L; // Wednesday, January 10 15:15:27 GMT
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.MONTH, ZoneId.of("Europe/Kyiv"))).isEqualTo(1706738400000L); // Thursday, February 1, 2024 0:00:00 GMT+02:00
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.MONTH, ZoneId.of("Europe/Amsterdam"))).isEqualTo(1706742000000L); // Monday, January 15, 2024 0:00:00 GMT+02:00
|
||||
|
} |
||||
|
|
||||
|
@Test |
||||
|
void testQuarterEnd() { |
||||
|
long ts = 1704899727000L; // Wednesday, January 10 15:15:27 GMT
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.QUARTER, ZoneId.of("Europe/Kyiv"))).isEqualTo(1711918800000L); // Monday, April 1, 2024 0:00:00 GMT+03:00 DST
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.QUARTER, ZoneId.of("Europe/Amsterdam"))).isEqualTo(1711922400000L); // Monday, April 1, 2024 1:00:00 GMT+03:00 DST
|
||||
|
|
||||
|
ts = 1711929600000L; // Monday, April 1, 2024 3:00:00 GMT+03:00
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.QUARTER, ZoneId.of("Europe/Kyiv"))).isEqualTo(1719781200000L); // Monday, July 1, 2024 0:00:00 GMT+03:00 DST
|
||||
|
assertThat(TimeUtils.calculateIntervalEnd(ts, IntervalType.QUARTER, ZoneId.of("America/New_York"))).isEqualTo(1711944000000L); // Monday, April 1, 2024 7:00:00 GMT+03:00 DST
|
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue