61

今日の時間、たとえば午後2時24分を考えると、午後2時30分に丸めるにはどうすればよいですか。

同様に、時刻が午後2時17分だった場合、午後2時15分に丸めるにはどうすればよいですか。

4

17 に答える 17

96

丸め

15分を切り捨てるには、モジュロを使用する必要があります。

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が指摘しているように、これもOKです(最後の行の置換。カレンダーが寛大な場合にのみ有効です)。

calendar.set(Calendar.MINUTE, unroundedMinutes + mod);

改善

正確にしたい場合は、小さいフィールドも切り捨てる必要があります。

calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

Apache Commons / LangのDateUtils.truncate()を使用して、これを行うこともできます。

calendar = DateUtils.truncate(calendar, Calendar.MINUTE);
于 2010-08-24T06:30:46.543 に答える
45

切り捨てるだけの場合、これはJavaTimeAPIを使用したより読みやすいバージョンです

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

于 2016-11-04T11:03:14.963 に答える
13

Java8のコメント付き実装。任意の丸め単位と増分を受け入れます。

 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;
  }

出典:私自身

于 2016-05-24T20:48:32.363 に答える
10

上記の答えを使用すると、数時間、数日などのオーバーフローを処理するためのあらゆる種類の興味深いコードができあがります。

エポックからの時間をミリ秒単位で使用します。

7.5分または7.5x60x1000=450000を追加します

900000の倍数に切り捨てます

new Date(900000 * ((date.getTime() + 450000) / 900000))

これが機能するのは、ms時間が開始する時刻がたまたま00:00:00であるためです。また、世界のすべてのタイムゾーンは15分ステップで変化するため、これは4分の1への丸めには影響しません。

(おっと、私は0が多すぎて、いくつかの重要な括弧を忘れました:それはまだ早すぎます)

于 2010-08-24T06:36:16.210 に答える
10

簡単です。1970年以降のクォーターの数を2倍にして、丸めて15分を掛けます。

long timeMs = System.System.currentTimeMillis();

long roundedtimeMs = Math.round( (double)( (double)timeMs/(double)(15*60*1000) ) ) * (15*60*1000) );

それを使用してDateまたはCalendarオブジェクトを設定します。

于 2012-01-04T08:22:43.510 に答える
6

素晴らしい投稿、ありがとうございました!それはまさに私が必要としていたものでした:)

これがjourworkに基づく私のコードです。

私のユースケースは、「午前11時47分なので、現在の5分間のフレームを表す2つの日付を設定したい:午前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()); 
于 2014-05-30T15:48:57.100 に答える
3

この単純なコードを使用できます...

int mode = min % 15;
if (mode > 15 / 2) {
    min = 15 - mode;
} else {
    min = 0 - mode;
}
cal.add(Calendar.MINUTE, min);
于 2010-08-24T06:54:04.090 に答える
3

javaInstantapiを使用するもう1つの代替アプローチ。

Instant instant =  Instant.now();
int intervalInMinutes = 10;
instant.truncatedTo(ChronoUnit.MINUTES).minus(instant.atZone(ZoneId.of("UTC")).getMinute() % (1* intervalInMinutes),ChronoUnit.MINUTES);
于 2019-10-07T08:58:07.623 に答える
2

次のように提供される最も近い任意のレベルに時間を切り捨てる必要がある場合Duration

static long truncateTo(long timeEpochMillis, Duration d) {
    long x = timeEpochMillis / d.toMillis();
    return x * d.toMillis();
}
于 2021-04-02T20:44:37.193 に答える
2

java.time

最新の日時APIを使用して実行することをお勧めします*

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        
        // Change it to the applicable ZoneId e.g. ZoneId.of("Asia/Kolkata")
        ZoneId zoneId = ZoneId.systemDefault();
        
        Stream.of(
                        "10:00", 
                        "10:05", 
                        "10:10", 
                        "10:15", 
                        "10:20", 
                        "10:25", 
                        "10:30"
            ).forEach(t -> System.out.println(roundToNearestQuarter(t, zoneId)));
    }

    static ZonedDateTime roundToNearestQuarter(String strTime, ZoneId zoneId) {
        LocalTime time = LocalTime.parse(strTime);
        return LocalDate.now()
                        .atTime(time)
                        .atZone(zoneId)
                        .truncatedTo(ChronoUnit.HOURS)
                        .plusMinutes(15 * Math.round(time.getMinute() / 15.0));
    }
}

出力:

2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:00+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:15+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]
2021-04-02T10:30+01:00[Europe/London]

ちょうど時間を探している場合は、取得したからZonedDateTime#toLocalTimeを取得するために使用します。LocalTimeZonedDateTime

Trail: DateTimeから最新の日時APIの詳細をご覧ください。


*java.util日時APIとそのフォーマットAPISimpleDateFormatは古く、エラーが発生しやすいです。それらの使用を完全に停止し、最新の日時APIに切り替えることをお勧めします。何らかの理由で、Java6またはJava7に固執する必要がある場合は、 Java.time機能のほとんどをJava6および7にバックポートするThreeTen-Backportを使用できます。AndroidプロジェクトおよびAndroidAPIレベルで作業している場合はまだJava-8に準拠していません。脱糖により利用可能な、Java 8以降のAPIと、AndroidプロジェクトでのThreeTenABPの使用方法を確認してください。

于 2021-04-02T22:17:40.870 に答える
1

おそらく、日付を操作するためのユーティリティライブラリを使用できます。たとえば、ここでは、便利なラウンドメソッドがあります。

http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/time/DateUtils.html#round%28java.util.Calendar,%20int%29

ここにコードの例があります:

    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));
于 2010-08-24T07:03:20.530 に答える
1
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();
}
于 2017-09-20T07:02:45.853 に答える
0

分がある場合は、次の関数でそれらを丸めることができます。
int minutes = i % 15 < 8 ? i / 15 * 15 : (i / 15 + 1) * 15;

于 2010-08-24T06:46:42.003 に答える
0
minutes = (int) (Math.round(minutes / 15.0) * 15.0);
于 2013-08-05T05:52:38.323 に答える
0

Stackoverflowで見つけたコードを使用して、次のコードを作成しました。四捨五入される四半期ごとに1分ごとに出力されます。

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 INFO 15:05,15:00
2016-08-16 15:14:31 INFO 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

于 2016-08-16T13:26:55.970 に答える
0

次の関数を使用して、分を前四半期getRecentQuater():Dateに丸めますgetSysDate_LastQuarterMins("dd.MM.yyyy HH:mm:ss"):String。:LocalDateTimeをDateに変換する

public static Date getRecentQuater() {
    LocalDateTime time = LocalDateTime.now();
    LocalDateTime lastQuarter = time.truncatedTo(ChronoUnit.HOURS).plusMinutes(getLastQuarterValue(time.getMinute()));
    System.out.println("lastQuarter LocalDateTime: " + lastQuarter);

    Date date = Date.from(lastQuarter.atZone(ZoneId.systemDefault()).toInstant());
    System.out.println("lastQuarter Date: " + lastQuarter);
    return date;
}
public static String getSysDate_LastQuarterMins(String dateFormat) {
    Date date = getRecentQuater();
    SimpleDateFormat ft = new SimpleDateFormat (dateFormat);
    String sysDate_RoundMin = ft.format(date);
    System.out.println("getSysDate_LastQuarterMins() LocalDateTime : "+sysDate_RoundMin);
    return sysDate_RoundMin;
}

getSysDate_LastQuarterMins() : Mon Jan 20 17:30:00 CET 2020

public static Date getSysDate_LastQuarterMins() {
    Calendar cal = Calendar.getInstance();
    cal.setTime( new Date(System.currentTimeMillis()) );

    int min = cal.get(Calendar.MINUTE);

    cal.set(Calendar.MINUTE, getLastQuarterValue(min));
    cal.set(Calendar.SECOND, 00);
    Date lastQuarter = cal.getTime();
    System.out.println("getSysDate_LastQuarterMins() Calendar : "+lastQuarter);
    return lastQuarter;
}

LastQuarter Value Round値は、次の機能から見つけることができます。関数呼び出しでいくつかの出力が提供されますdiaplayLastQuarter_RoundValue(min)

Min: 10, LastQuarter:  0, Round: 15
Min: 24, LastQuarter: 15, Round: 30
Min: 36, LastQuarter: 30, Round: 30
Min: 37, LastQuarter: 30, Round: 30
Min: 38, LastQuarter: 30, Round: 45
Min: 39, LastQuarter: 30, Round: 45
Min: 44, LastQuarter: 30, Round: 45
Min: 57, LastQuarter: 45, Round: 00 [57, 07:45:00, 08:00:00]
public static void diaplayLastQuarter_RoundValue(int minutes) {
    System.out.format("Min: %2d, LastQuarter: %2d, Round: %2d\n",
            minutes, getLastQuarterValue(minutes), getRoundValue(minutes));
}
public static int getLastQuarterValue(int minutes) {
    int min = 15 * (minutes / 15);
    //System.out.println("Min: "+minutes+", getLastQuarterValue : "+ min);
    return min;
}
public static int getRoundValue(int minutes) {
    getLastQuarterValue(minutes);
    int minRound = (int) (Math.round(minutes / 15.0) * 15.0);
    //System.out.println("Min: "+minutes+", getRoundValue : "+minRound);
    return minRound;
}
于 2020-01-20T16:24:16.703 に答える
0

誰かが最も近い(上または下)5または15間隔を取得することに興味がある場合、私はその仕事をするモジュールを使用して関数を作成しました。

public LocalTime roundToTheNearestInterval(LocalTime original, Integer measurementInterval) {
        LocalTime nearest;
        int mod;
        switch (measurementInterval) {
            case 5:
                mod = original.getMinute() % 5;
                nearest = mod >= 3 ?
                        original.truncatedTo(ChronoUnit.HOURS)
                                .plusMinutes((long) 5 * (original.getMinute() / 5) + 5) :
                        original.truncatedTo(ChronoUnit.HOURS)
                                .plusMinutes((long) 5 * (original.getMinute() / 5));
                break;
            case 15:
                mod = original.getMinute() % 15;
                nearest = mod >= 8 ?
                        original.truncatedTo(ChronoUnit.HOURS)
                                .plusMinutes((long) 15 * (original.getMinute() / 15) + 15) :
                        original.truncatedTo(ChronoUnit.HOURS)
                                .plusMinutes((long) 15 * (original.getMinute() / 15));
                break;
            default:
                nearest = original;
        }
        return nearest;
    }

この単体テストで試すことができます

 @Test
    void roundToTheNearestInterval() {
        //given
        LocalTime originalTime1 = LocalTime.of(6, 31, 15);
        LocalTime originalTime2 = LocalTime.of(19, 13, 42);
        LocalTime originalTime3 = LocalTime.of(6, 37, 11);
        LocalTime originalTime4 = LocalTime.of(19, 40, 34);
        Integer measurementInterval_5min = 5;
        Integer measurementInterval_15min = 15;

        MyService myService = new MyService();

        //when
        LocalTime rounded1_5min = myService.roundToTheNearestInterval(originalTime1, measurementInterval_5min);
        LocalTime rounded2_5min = myService.roundToTheNearestInterval(originalTime2, measurementInterval_5min);

        LocalTime rounded1_15min = myService.roundToTheNearestInterval(originalTime3, measurementInterval_15min);
        LocalTime rounded2_15min = myService.roundToTheNearestInterval(originalTime4, measurementInterval_15min);

        //then
        assertEquals(LocalTime.of(6, 30, 0), rounded1_5min);
        assertEquals(LocalTime.of(19, 15, 0), rounded2_5min);
        assertEquals(LocalTime.of(6, 30, 0), rounded1_15min);
        assertEquals(LocalTime.of(19, 45, 0), rounded2_15min);

    }
于 2021-07-16T16:58:55.980 に答える