0

I’m trying to calculate the time by adding minutes to given date-time. It’s works well with other times but not for the DST times [ Canada Eastern time ].

 public static GregorianCalendar addMinuts(GregorianCalendar newDate, int minutes) {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(newDate.getTime());

        Log.i("UtilApp", "expiry date before add minutes " + cal.getTime());
        cal.add(Calendar.MINUTE, minutes);
        Log.i("UtilApp", "expiry date after add " + minutes + " minutes " + cal.getTime());
        return setGreCalendar(cal.getTime());
    }

 public static GregorianCalendar setGreCalendar(Date date) {
        Date date1;
        GregorianCalendar gregorianCalendar = new GregorianCalendar();
        if (date != null) {
            date1 = date;
            gregorianCalendar.setTime(date1);
        }
        return gregorianCalendar;
    }

For example:- I added 225 minutes which is 3 hrs and 45 minutes to 9th march, and it gives the exact date and time as DST is not in effect.

9th march

While on March 10th, DST is in effect, so instead of getting 03:45, I get 04:45 with the same 225 minutes. The calendar is skipping the time between 2:00 and 3:00 due to DST.

10th March

I want it to ignore the DST adjustments. I tried with the time-zone, Local date-time but it didn’t work as expected. Any help would be appreciated.

4
  • 3
    Unless you are using a Java version prior to Java 8, you should be using the date-time API.
    – Abra
    Commented May 30 at 6:07
  • 1
    I want it to ignore the DST adjustments. I tried with the time-zone, Local date-... Then your calculation will be wrong whichever API you use. But as it happens, you should be using java.time
    – g00se
    Commented May 30 at 7:06
  • Stop using those terribly flawed legacy date-time classes. Use only java.time classes. An implementation is included with Android 26+. For earlier Android, the latest tooling provides most of the java.time functionality through “API de-sugaring”. Commented May 30 at 14:08
  • No, you really don’t want to ignore Daylight Saving Time (DST). On the day of DST cutover “Spring ahead”, you will be cheating your users by one hour short if you do not account for DST. Furthermore, your desired time landing in the cutover hour does not exist on that day in that zone, so you are using a nonsense value. Commented May 30 at 14:12

2 Answers 2

1

You wrote (in your question):

I tried with the time-zone, Local date-time but it didn’t work as expected.

I don't know if you are referring to class LocalDateTime, because if you are then it should work as you expect since class LocalDateTime has no time zone whereas class Calendar does which its subclass, GregorianCalendar, inherits.

The below code gives your expected result when adding minutes to a LocalDateTime, regardless of daylight savings adjustments.

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class AdMinute {

    public static void main(String[] args) {
        LocalDate ld = LocalDate.of(2024, 3, 10);
        LocalDateTime ldt = ld.atStartOfDay();
        System.out.println("Org: " + ldt);
        System.out.println("Add: " + ldt.plus(225, ChronoUnit.MINUTES));
    }
}

Here is the output when running the above code:

Org: 2024-03-10T00:00
Add: 2024-03-10T03:45

Note that I am in Israel and our daylight savings started at March 29. At 2:00 am clocks were moved forward to 3:00 am. If I replace the date, in the above code, with 29 (rather than 10), I still get the same result. Hence using LocalDateTime is not affected by daylight savings adjustments.

Refer to this tutorial.

2
  • 1
    Abra is right and so am I ;)
    – g00se
    Commented May 30 at 7:23
  • It worked. The way i was adding the minutes using LocalDateTime seems wrong. Thanks alot it helped!
    – DigitV23
    Commented May 31 at 13:19
1

tl;dr

Instant.now().plus( Duration.ofMinutes( 225 ) )

Ignoring DST is misguided

The Answer by Abra is spot-on correct in answering your direct Question about ignoring time zone.

Unfortunately, your Question is misguided. You are modeling an expiry. So ignoring temporal anomalies such as Daylight Saving Time (DST) while working in date/time of a particular locality is not an option.

In your example, you would wind up trying to represent a time of day that does not exist, landing in the hour skipped over during a “Spring ahead” cutover in DST. And your approach would end up cheating your users of an hour during a “Spring ahead” DST cutover while giving an extra hour during the “Fall back” DST cutover.

UTC time

The real solution is to not use time zone and not use the locality date/time. Instead, use UTC time.

Temporal meridian

UTC is the temporal meridian. You can think of this UTC meridian as standing at the Royal Observatory, Greenwich where the noon is when the sun is directly overhead. Noon in places eastward occur a certain number of hours-minutes-seconds earlier, while noon in places westward occur a certain number of hours-minutes-seconds later.

Offset from UTC

Those hours-minutes-seconds are called an offset from UTC. For example, people in the region of Paris France right now have set their clocks to be two hours ahead of UTC.

Political time

The politicians in every region occasionally decide to change the offset to be observed by the people in their jurisdiction. Daylight Saving Time but one of many reasons they may decide so. Internal politics, diplomacy, war, and occupation are some other reasons.

Time zone

The history of these changes in the past, present, and future is a time zone. A time zone is named in the format of Continent/Region such as Europe/Paris.

UTC time is stable

The point here is that political time, via time zones, is always under threat of being changed. In contrast, UTC time, time tracked with an offset of zero, is stable and unchanging.

So programmers & sysadmins should think of UTC time (zero offset) as the One True Time. All others are but a variation. With few exceptions, the clocks on your servers should be set to UTC, logging should be in UTC, and data storage & exchange should be in UTC.

Avoid legacy date-time classes

One more crucial point: You are using terribly flawed date-time classes that were many years ago supplanted entirely by the modern java.time classes defined in JSR 310. Never use them. Use only the java.time classes.

Example code

Duration

If you want to set an expiry of 225 minutes, use Duration class to represent that span of time unattached to the timeline.

Duration duration = Duration.ofMinutes( 225 ) ;

Instant

If you mean 225 minutes from now, determine the current moment as seen in UTC. For that, use the class Instant. An Instant object represents a moment, a particular point on the timeline, as seen with an offset of zero.

Instant now = Instant.now() ;

Add the duration to determine the expiry.

Instant expiry = now.plus( duration ) ;

Now you have an expiry that is impervious to the whims of politicians.

This Instant object is what, in your case, should be used for data storage, data exchange, and business logic.

ZonedDateTime

When it comes time to display that value to the user, adjust to their desired/expected time zone.

ZoneId zoneId = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = expiry.atZone( zoneId ) ;

Now you have an object than represents that same moment as seen through the wall-clock & wall-calendar used by the people of that region. A second way to view the very same moment.

Do not store or exchange this ZonedDateTime object. In your case, you should be using Instant for most purposes other than presentation to user, as mentioned above.

DateTimeFormatter

Generate text localized for the user.

Locale locale = Locale.CANADA_FRENCH ; 
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( locale) ;
String output = zdt.format( formatter ) ;

Not the answer you're looking for? Browse other questions tagged or ask your own question.