-3

We have a requirement to Round by next quarter minutes in Java code, for example:

  1. if current date time is 2020-05-28T10:01:00 then, round up to next quarter to make it 2020-05-28T10:15:00

  2. if current date time is 2020-05-28T10:15:01 then, round up to next quarter to make it 2020-05-28T10:30:00

  3. if current date time is 2020-05-28T10:46:15 then, round up to next quarter to make it 2020-05-28T11:00:00

  4. if current date time is 2020-12-31T23:47:00 then, round up to next quarter to make it 2021-01-01T00:00:00

Can someone please provide Java code to achieve this. Any help is appreciated.


Tried below code but unable to get the output which I'm looking for:

import java.util.Calendar;
import java.util.Date;

    public class Main {
        public static void main(String[] args) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            int round = calendar.get(Calendar.MINUTE) % 15;
            calendar.add(Calendar.MINUTE, round < 8 ? -round : (15-round));
            calendar.set( Calendar.SECOND, 0 );
            System.out.println(calendar.getTime());
        }
    }
Esterlinkof
  • 1,444
  • 3
  • 22
  • 27
  • 4
    Please post the code you've written so far, Stack Overflow is not a service to write your code for free ;) you must show some effort! – Óscar López May 30 '20 at 21:18
  • I do not see the question? – darclander May 30 '20 at 21:18
  • Since I am new to Java... so asking for help.. but i edited my question with Java code – abhishek karan May 30 '20 at 21:25
  • 1
    FYI, the terribly flawed date-time classes such as [`java.util.Date`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/tutorial/datetime/TOC.html) classes built into Java 8 and later. – Basil Bourque May 31 '20 at 03:50

2 Answers2

3

This can be easily done using the LocalDateTime class from the java.time package, which you should be using anyway1.

public static LocalDateTime roundUpToQuarter(LocalDateTime datetime) {
    int minutesToAdd = 15 - (datetime.getMinute() % 15);
    return datetime
        .plusMinutes(minutesToAdd)
        .truncatedTo(ChronoUnit.MINUTES);
}

This calculation involving the modulus operator makes sure that we get the number of minutes to add to go to the next full quarter. The truncatedTo(ChronoUnit.MINUTES) call makes in turn sure that all fields smaller than 'minutes' are set to zero.

Update: I'm not certain of your exact use case, but, as Basil pointed out, if you want to represent a moment on the timeline, then you also need a timezone or offset. This can be done by replacing LocalDateTime instances with ZonedDateTime in the abovementioned method.


1 The Date, Calendar and SimpleDateFormat classes are obsolete. They may work in simple cases, but they will cause trouble in more complex cases. See What's wrong with Java Date & Time API?.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • C:\Users\*****\javaCode\ProcessDefinitionJavaCode.java:35: error: cannot find symbol int minutesToAdd = 15 - (now.getMinutes() % 15); ^ symbol: method getMinutes() location: variable now of type LocalDateTime 1 error – abhishek karan May 30 '20 at 23:43
  • It's `getMinute` instead of `getMinutes`. – MC Emperor May 31 '20 at 00:11
  • It's Jre 1.8, strange thing is only ow.getMinutes() causing issue. when i tried below to see if error coming for othet thing as well, but below is working fine without error. And yes imported LocalDateTime. LocalDateTime newTime = now.plusMinutes(1).truncatedTo(ChronoUnit.MINUTES); – abhishek karan May 31 '20 at 00:12
  • Thanks for help:. do you know to get the output in some variable. When I am trying to convert,it's throwing an error: incompatible types: LocalDateTime cannot be converted to Date – abhishek karan May 31 '20 at 00:22
  • I think I found it: Date d = java.sql.Timestamp.valueOf( newTime); – abhishek karan May 31 '20 at 00:31
  • Only thing left, if I can pass Input datetime to this request. How can i input the requested datetime? – abhishek karan May 31 '20 at 00:39
  • 1
    Good Answer, except that I cannot think of any scenario where calling `LocalDateTime.now()` is the right thing to do, since that class cannot represent a moment. I suggest changing to [`ZonedDateTime`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/ZonedDateTime.html). See such [code run live at IdeOne.com](https://ideone.com/TbDhlK). – Basil Bourque May 31 '20 at 03:48
  • @BasilBourque It cannot, indeed. But to me, the exact use case of OP was not entirely clear. But judging by the comments it looks like the datetime should be timezone-sensitive. I used `LocalDateTime.now()` as an example. – MC Emperor May 31 '20 at 07:50
  • @abhishekkaran I've updated the answer, to include a method returning a rounded time. – MC Emperor May 31 '20 at 13:32
  • I can two issues: when i pass input as 2020-11-30T23:47:00 , Output is coming as 2020-11-30T23:00:00 expected Output should be 2020-12-01T00:00:00 Second issue: when passing Input as 2020-12-31T23:47:00 , Output is coming as 2020-12-31T23:00:00, actual output should be 2021-01-01T00:00:00 ( i.e next year) Surprisingly things are working good till Oct end i.e 2020-10-31T23:47:00 is workign and showing output as 2020-11-01T00:00:00.... so not sure what the issue with Nov and Dec – abhishek karan May 31 '20 at 16:13
  • @abhishekkaran It depends on how you are passing it. How are you passing your input? – MC Emperor May 31 '20 at 18:31
  • @abhishekkara This occurs due to daylight savings time. – MC Emperor May 31 '20 at 18:39
  • Thanks a ton. Yes, it was due to Daylight saving. I tested with passing timezone and now it's working as expected... Thanks again. – abhishek karan May 31 '20 at 23:30
0

You can try below code.

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date(1609438620000l));
    int fraction = calendar.get(Calendar.MINUTE) / 15;
    switch (fraction) {
    case 0: {
        calendar.set(Calendar.MINUTE, 0);
        break;
    }
    case 1: {
        calendar.set(Calendar.MINUTE, 15);
        break;
    }
    case 2: {
        calendar.set(Calendar.MINUTE, 30);
        break;
    }
    default: {
        calendar.set(Calendar.MINUTE, 45);
        break;
    }
    }
    calendar.add(Calendar.MINUTE, 15);
    calendar.set(Calendar.SECOND, 0);
    System.out.println(calendar.getTime());
vijay krishna
  • 514
  • 4
  • 14
  • Thanks for quick response. But I am getting MyClass.java uses or overrides a deprecated API error when try to run your code. Any suggestion? – abhishek karan May 30 '20 at 21:41
  • You can suppress the warnings. Add below line on top of the method. @SuppressWarnings("deprecation") – vijay krishna May 30 '20 at 21:47
  • I've updated my answer using Calendar since you're already using it. Hope it helps – vijay krishna May 30 '20 at 21:55
  • Thanks it's working but below I am getting: Input: 2020-05-30T17:57:07 output: 2020-05-30T18:00:07 Expected Output should be 2020-05-30T18:00:00 – abhishek karan May 30 '20 at 21:57
  • Did you miss `calendar.set(Calendar.SECOND, 0);` ? – vijay krishna May 30 '20 at 22:03
  • Gotcha...I missed it... Thanks a ton. I will verify all scenarios and let u know on this. – abhishek karan May 30 '20 at 22:11
  • Vijay .... is there way I can Input the dateTime manually in this code to check all scenario? For example if i need to pass "2020-05-31T10:30:00.416-04:00" as a Input – abhishek karan May 30 '20 at 22:23
  • FYI, the terribly flawed date-time classes such as [`java.util.Date`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [*java.time*](https://docs.oracle.com/javase/tutorial/datetime/TOC.html) classes built into Java 8 and later. – Basil Bourque May 31 '20 at 03:50
  • I can two issues: when i pass input as 2020-11-30T23:47:00 , Output is coming as 2020-11-30T23:00:00 expected Output should be 2020-12-01T00:00:00 Second issue: when passing Input as 2020-12-31T23:47:00 , Output is coming as 2020-12-31T23:00:00, actual output should be 2021-01-01T00:00:00 ( i.e next year) Surprisingly things are working good till Oct end i.e 2020-10-31T23:47:00 is workign and showing output as 2020-11-01T00:00:00.... so not sure what the issue with Nov and Dec – – abhishek karan May 31 '20 at 16:21