Search code examples
javaandroiddatedatetimeandroid-calendar

How to get the total number of minutes in the day so far?


How do you get the total number of minutes in the day so far in Java (Android)? Is this possible? For example, if it was 12:37am, I would want it to return int 37 (37 minutes so far that day). Or if it was 1:41am, I would want it to return int 101 (101 minutes so far that day), or if it 12:20pm, it would return int 740 (740 total minutes that day).


Solution

  • tl;dr

    ZoneId z = ZoneId.of( "America/Montreal" ) ;
    ZonedDateTime zdt = ZonedDateTime.now( z ) ;
    long minutesIntoTheDay = ChronoUnit.MINUTES.between( 
        zdt.toLocalDate().atStartOfDay( z ) ,
        zdt 
    );
    

    Time Zone

    The other answers are incorrect in that they fail to account for time zone. If you want minutes since start of day, which day? The day starting in Kolkata, Paris, or Montréal? A 23-hour, 24-hour, 25-hour, or some other length day?

    Specify a proper time zone name. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

    Using java.time

    Get the current moment, ZonedDateTime, for your desired/expected time zone by specifying a ZoneId.

    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    ZonedDateTime now = ZonedDateTime.now( zoneId );
    

    To get the number of minutes into the day, get the first moment of the day, and then calculated elapsed time.

    ZonedDateTime startOfDay = now.toLocalDate().atStartOfDay( z );
    

    Calculate elapsed time either as a Duration or use the ChronoUnit enum.

    Duration duration = Duration.between( startOfDay , now );
    long minutesIntoTheDay = duration.toMinutes();
    

    …or…

    long minutesIntoTheDay = ChronoUnit.MINUTES.between( startOfDay , now );
    

    Example: Europe/Amsterdam

    Here is an example showing the DST cutover (“Spring forward”) for the Netherlands in time zone Europe/Amsterdam this year of 2017, on March 26 at 2 AM.

    LocalDate march26 = LocalDate.of ( 2017, Month.MARCH, 26 );
    LocalTime twoAm = LocalTime.of ( 2, 0 );
    ZoneId z = ZoneId.of ( "Europe/Amsterdam" );
    ZonedDateTime start = march26.atStartOfDay ( z );
    ZonedDateTime stop = ZonedDateTime.of ( march26, twoAm, z );
    long minutes = ChronoUnit.MINUTES.between ( start, stop );
    Duration duration = Duration.between ( start, stop );
    long durationAsMinutes = duration.toMinutes ( );
    int minuteOfDay = stop.get ( ChronoField.MINUTE_OF_DAY );
    

    Dump to console.

    System.out.println ( "start: " + start );
    System.out.println ( "stop: " + stop );
    System.out.println ( "minutes: " + minutes );
    System.out.println ( "FYI: 4 * 60 = " + ( 4 * 60 ) + " | 3 * 60 = " + ( 3 * 60 ) + " | 2 * 60 = " + ( 2 * 60 ) );
    System.out.println ( "duration.toString(): " + duration + " | durationAsMinutes: " + durationAsMinutes );
    System.out.println ( "minuteOfDay: " + minuteOfDay );
    

    You can see this code run live at IdeOne.com.

    start: 2017-03-26T00:00+01:00[Europe/Amsterdam]

    stop: 2017-03-26T03:00+02:00[Europe/Amsterdam]

    minutes: 120

    FYI: 4 * 60 = 240 | 3 * 60 = 180 | 2 * 60 = 120

    duration.toString(): PT2H | durationAsMinutes: 120

    minuteOfDay: 180

    Note in the output:

    • The offset-from-UTC changes by an hour, going from +01:00 to +02:00.
    • The time-of-day we requested was 2 AM, but there is no such time-of-day on that date. Two o’clock in the morning simply does not exist on that date as the clocks jumped ahead an hour. Of course, space-time did not bend nor warp. Only two hours of actual time elapsed between midnight and 3 AM, not three. The designers of the java.time classes chose to resolve the problem by adjusting the time-of-day value ahead to the valid time-of-day. Read the doc to be sure you understand and agree with such behavior.
    • The result of ChronoField.MINUTE_OF_DAY is not correct/precise because that feature accounts only for generic 24-hour days rather than actual anomalous dates such as this date with DST cutover. We see 180 minutes whereas only 120 minutes actually elapsed.

    CORRECTION: This Answer formerly advised using ChronoField.MINUTE_OF_DAY. That was poor advice as that feature uses generic 24-hour days. Anomalies such as Daylight Saving Time (DST) are ignored. So the results may not be precise/correct for particular dates in certain time zones. This behavior is clearly documented:

    ChronoField MINUTE_OF_DAY

    public static final ChronoField MINUTE_OF_DAY

    The minute-of-day.

    This counts the minute within the day, from 0 to (24 * 60) - 1. This field has the same meaning for all calendar systems.

    When parsing this field it behaves equivalent to the following: The value is validated in strict and smart mode but not in lenient mode. The value is split to form MINUTE_OF_HOUR and HOUR_OF_DAY fields.


    About java.time

    The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

    The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

    To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

    Where to obtain the java.time classes?