Учитывая сегодняшнее время, например. 14:24, как мне добраться до 2:30 вечера?
Аналогично, если время было 2:17 вечера, как мне добраться до раунда до 2:15 вечера?
Учитывая сегодняшнее время, например. 14:24, как мне добраться до 2:30 вечера?
Аналогично, если время было 2:17 вечера, как мне добраться до раунда до 2:15 вечера?
Вам нужно будет использовать modulo для усечения четверти часа:
Date whateverDateYouWant = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(whateverDateYouWant);
int unroundedMinutes = calendar.get(Calendar.MINUTE);
int mod = unroundedMinutes % 15;
calendar.add(Calendar.MINUTE, mod < 8 ? -mod : (15-mod));
Как указано EJP, это также нормально (замена для последней строки, действительна только в том случае, если календарь lenient):
calendar.set(Calendar.MINUTE, unroundedMinutes + mod);
Если вы хотите быть точным, вам также придется обрезать меньшие поля:
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Вы также можете использовать DateUtils.truncate() из Apache Commons/Lang, чтобы сделать это:
calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
Если вы просто хотите округлить, это более читаемая версия, используя Java Time API:
LocalDateTime time = LocalDateTime.now();
LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS)
.plusMinutes(15 * (time.getMinute() / 15));
выход:
2016-11-04T10: 58: 10,228
2016-11-04T10: 45: 00
Это просто, найдите число кватеров с 1970 года как двойное, округлите его и умножьте на 15 минут:
long timeMs = System.System.currentTimeMillis();
long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );
Задайте для этого объект Date или Calendar.
С ответом выше вы получаете весь интересный код для обработки переполнения часов, дней и т.д.
Я использовал бы время в ms с эпохи.
добавить 7.5minutes или 7.5x60x1000 = 450000
и усечь до кратного 900000
new Date(900000 * ((date.getTime() + 450000) / 900000))
Это работает, потому что время, в которое начинается время ms, составляет 00:00:00. И поскольку все часовые пояса в мире изменяются с шагом 15 минут, это не влияет на округление до кварталов.
(Упс, у меня было слишком много 0 и забыли некоторые важные круглые скобки: все еще слишком рано)
Прокомментированная реализация для Java 8. Принимает произвольные блоки округления и приращения:
public static ZonedDateTime round(ZonedDateTime input, TemporalField roundTo, int roundIncrement) {
/* Extract the field being rounded. */
int field = input.get(roundTo);
/* Distance from previous floor. */
int r = field % roundIncrement;
/* Find floor and ceiling. Truncate values to base unit of field. */
ZonedDateTime ceiling =
input.plus(roundIncrement - r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
ZonedDateTime floor =
input.plus(-r, roundTo.getBaseUnit())
.truncatedTo(roundTo.getBaseUnit());
/*
* Do a half-up rounding.
*
* If (input - floor) < (ceiling - input)
* (i.e. floor is closer to input than ceiling)
* then return floor, otherwise return ceiling.
*/
return Duration.between(floor, input).compareTo(Duration.between(input, ceiling)) < 0 ? floor : ceiling;
}
Источник: сам
Замечательный пост, большое спасибо, ребята! Это было именно то, что мне нужно:)
Здесь мой код основан на работе jour.
My usecase "Учитывая это 11:47 утра, я хочу установить две даты, символизирующие текущий 5-минутный кадр: 11:45 утра и 11:50 утра"
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
int modulo = calendar.get(Calendar.MINUTE) % 5;
if(modulo > 0) {
calendar.add(Calendar.MINUTE, -modulo);
}
myObject.setStartDate(calendar.getTime());
calendar.add(Calendar.MINUTE, 5);
myObject.setDueDate(calendar.getTime());
Вы можете использовать этот простой код...
int mode = min % 15;
if (mode > 15 / 2) {
min = 15 - mode;
} else {
min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);
Возможно, вы можете использовать служебную библиотеку для управления датами, здесь, например, у вас есть круглый метод, который может быть вам полезен:
Вот пример кода:
FastDateFormat formatter = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT;
Date now = new Date();
System.out.println("now = " + formatter.format(now));
// Get nearest second
Date nearestSecond = DateUtils.round(now, Calendar.SECOND);
System.out.println("nearestSecond = " + formatter.format(nearestSecond));
// Get nearest minute
Date nearestMinute = DateUtils.round(now, Calendar.MINUTE);
System.out.println("nearestMinute = " + formatter.format(nearestMinute));
// Get nearest hour
Date nearestHour = DateUtils.round(now, Calendar.HOUR);
System.out.println("nearestHour = " + formatter.format(nearestHour));
public static Date getCurrentDateTimeWithQuarterRounding() {
final Calendar calendar = new GregorianCalendar();
calendar.setTime(new Date());
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
final int minutes = calendar.get(Calendar.MINUTE);
if (minutes < 15) {
calendar.set(Calendar.MINUTE, 0);
} else if (minutes >= 45) {
calendar.set(Calendar.MINUTE, 45);
} else if (minutes < 30) {
calendar.set(Calendar.MINUTE, 15);
} else {
calendar.set(Calendar.MINUTE, 30);
}
return calendar.getTime();
}
Если у вас есть минуты, вы можете объединить их со следующей функцией:
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;
minutes = (int) (Math.round(minutes / 15.0) * 15.0);
Используя некоторый код, который я нашел в Stackoverflow, я создал следующий код. Он будет выводить каждую минуту в квартал, в котором он будет округлен.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
DateTimeFormatter Datum_Format = DateTimeFormatter.ofPattern("HH:mm");
LocalDateTime time = LocalDateTime.now();
for(int i=0; i<=59; i++) {
time = time.withMinute(i);
int Minute = time.getMinute();
int Quarter = 15 * (int) Math.round(Minute / 15);
if (Quarter == 60) {
Time2 = time.plusHours(1);
Time2 = Time2.withMinute(0);
LOG.info (Datum_Format.format(time) + "," + Datum_Format.format(Time2));
}
else {
Time2 = time;
Time2 = Time2.withMinute(Quarter);
LOG.info (Datum_Format.format(time) + "," + Datum_Format.format(Time2));
}
}
Когда я вывожу код на консоль, вам нужно будет заменить LOG.info чем-то вроде System.out.println.
Результат:
2016-08-16 15:14:31 ИНФОРМАЦИЯ 15: 05,15: 00
2016-08-16 15:14:31 ИНФОРМАЦИЯ 15: 06,15: 00
2016-08-16 15:14:31 INFO 15: 07,15: 00
2016-08-16 15:14:31 INFO 15: 08,15: 15
2016-08-16 15:14:31 INFO 15: 09,15: 15
2016-08-16 15:14:31 ИНФОРМАЦИЯ 15: 10,15: 15
Еще один альтернативный подход с использованием java Instant api.
Instant instant = Instant.now();
int intervalInMinutes = 10;
instant.truncatedTo(ChronoUnit.MINUTES).minus(instant.atZone(ZoneId.of("UTC")).getMinute() % (1* intervalInMinutes),ChronoUnit.MINUTES);