Skip to content

Instantly share code, notes, and snippets.

@jkebinger
Created September 11, 2023 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkebinger/626c0c8b4838659ccb4e89fd357f5e8f to your computer and use it in GitHub Desktop.
Save jkebinger/626c0c8b4838659ccb4e89fd357f5e8f to your computer and use it in GitHub Desktop.
Generate a list of hourly or daily time spans in UTC milliseconds in any timezone
package cloud.prefab.server.utils;
import cloud.prefab.domain.Internal;
import com.google.common.base.Preconditions;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
public class TimeIntervalGenerator {
public static List<TimeSpan> generate(
long startUtc,
long endUtc,
String timezoneName,
Internal.TimeInterval timeInterval
) {
Preconditions.checkArgument(
startUtc <= endUtc,
"Start time %s must be less than end time %s",
startUtc,
endUtc
);
// timezone convert so we get correct offset
// snap/truncate to the time unit
ZoneId timezone = ZoneId.of(timezoneName);
ChronoUnit chronoUnit = mapInterval(timeInterval);
ZonedDateTime zonedStartTime = ZonedDateTime.ofInstant(
Instant.ofEpochMilli(startUtc),
timezone
);
ZonedDateTime zonedEndTime = ZonedDateTime.ofInstant(
Instant.ofEpochMilli(endUtc),
timezone
);
ZonedDateTime actualEndTime = zonedEndTime
.truncatedTo(chronoUnit)
.plus(1, chronoUnit);
List<TimeSpan> timeSpans = new ArrayList<>();
ZonedDateTime currentTime = zonedStartTime.truncatedTo(chronoUnit);
while (true) {
ZonedDateTime nextTime = currentTime.plus(1, chronoUnit);
if (nextTime.isAfter(actualEndTime)) {
break;
}
timeSpans.add(new TimeSpan(currentTime, nextTime));
currentTime = nextTime;
}
return timeSpans;
}
public record TimeSpan(ZonedDateTime start, ZonedDateTime end) {}
private static ChronoUnit mapInterval(Internal.TimeInterval timeInterval) {
switch (timeInterval) {
case HOURLY:
return ChronoUnit.HOURS;
case DAILY:
return ChronoUnit.DAYS;
default:
throw new IllegalArgumentException(
"Unrecognized unit %s".formatted(timeInterval)
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment