I have a ZonedDateTime stored in a timeStamp
variable.
I also have a Duration barDuration
that can be one minute, 5 minutes, 15 minutes, one hour, 6 hours or one day.
I'm plotting a candle chart which width is barDuration
.
If the bar duration is set to 1 minute, I need that bars to start at a round minute (e.g. 9:43:00).
If it is set to 5 minutes, I need the bars to start at 9:45, 9:50, 9:55 etc.
If is is set to 15 minutes, then the bars start at 9:45, 10:00, 10:15, etc.
When barDuration
is 1 minute, I know I can compute the end time of the bar using:
timeStamp.truncatedTo(ChronoUnit.MINUTES).plus(barDuration)
But this is hard-coded and I want to use the barDuration
directly to perform the truncation. How can this be done?
Edit:
I found here a solution with Clock
s:
Clock baseClock = Clock.tickMinutes(timeStamp.getZone());
Clock barClock = Clock.tick(baseClock, barDuration);
LocalDateTime now = LocalDateTime.now(barClock);
LocalDateTime barEndTime = now.plus(barDuration);
This would work, but it is not based to my timeStamp
, but on using LocalDateTime.now()
, which is not what I want (I'm not sure the local time on my machine is synchronized with the timestamp I retrieve from a remote server).
As a humble supplement to JB Nizets answer here’s (EDIT:) a Java 9 version that is more time unit neutral.
static ZonedDateTime truncateToDuration(ZonedDateTime zonedDateTime, Duration duration) {
ZonedDateTime startOfDay = zonedDateTime.truncatedTo(ChronoUnit.DAYS);
return startOfDay.plus(duration.multipliedBy(
Duration.between(startOfDay, zonedDateTime).dividedBy(duration)));
}
I have not tested thoroughly, but I expect it to work with rounding to for example 500 nanos too. I divide the duration since start of day with the duration to round to, and immediately multiply back, just to obtain a whole number of that duration.
Funny results will probably occur if your duration doesn’t divide into an hour, or your day starts on something else than a whole hour (if that occurs at all).