0

Hi I've tried to substract hour from a Date using Date.getTime() - (time in ms ) but the result is not correct , there is always a slight gap compared to the good result, any idea ?

if(hoursToBeSubstracted<1) { 
            float toMinute = hoursToBeSubstracted*60;
            return new Date((long)(d1.getTime()-toMinute*60000));
        }
        return new Date((long)(d1.getTime() - 3600 * hoursToBeSubstracted * 1000));

Example of output :

Before operation Thu Dec 01 13:27:30 CET 2022
Substracting 60.0 minutes
After operation Thu Dec 01 12:28:31 CET 2022
Before operation Wed Nov 30 16:48:52 CET 2022
Substracting 60.0 minutes
After operation Wed Nov 30 15:49:53 CET 2022
Before operation Wed Nov 30 16:48:52 CET 2022
Substracting 60.0 minutes
After operation Wed Nov 30 15:49:53 CET 2022
Before operation Wed Nov 30 16:48:52 CET 2022
Substracting 60.0 minutes
After operation Wed Nov 30 15:49:53 CET 2022
Before operation Thu Dec 01 13:27:30 CET 2022
Substracting 60.0 minutes
After operation Thu Dec 01 12:28:31 CET 2022
LucasG
  • 11
  • 3
  • Can you show the values you used/expected? I'm interested in this *slight gap*… – deHaar Dec 02 '22 at 10:05
  • I've added the output – LucasG Dec 02 '22 at 10:07
  • 1
    why did you use `float` ? – Gyro Gearless Dec 02 '22 at 10:08
  • because in the program we must be able to choose how much we want to subtract and it is of the form 1f hour so it can also be 0.1f hour (sry bad english) – LucasG Dec 02 '22 at 10:11
  • 3
    The cleanest way around this is to use the new `java.time` API which provides methods like `minusHours` and so on on `ZonedDateTime` (and other types where it makes sense). The old `java.util.Date` is a terrible API and you should be switching to something saner anyway. – Joachim Sauer Dec 02 '22 at 10:11
  • Try taking a look at this (html tutorial with java time) https://drive.google.com/file/d/1gjHmdC-BW0Q2vXiQYmp1rzPU497sybNy/view?usp=share_link – Samuel Marchant Dec 02 '22 at 11:42
  • I strongly recommend you don’t use `Date`. That class is poorly designed and long outdated. Instead use `Instant` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Dec 02 '22 at 20:38
  • I have only reproduced approximately. I get `Fri Dec 02 21:43:14 CET 2022` before and `Fri Dec 02 20:44:01 CET 2022` after, so apparently 47 seconds too late where you seem to get 61 seconds too late. – Ole V.V. Dec 02 '22 at 20:46
  • In `d1.getTime() - 3600 * hoursToBeSubstracted * 1000` you are subtracting a relatively small `float` value from a relatively large one, which gives an inaccurate result. See the linked original question [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Ole V.V. Dec 02 '22 at 21:13

1 Answers1

4

java.time

The java.time API, released with Java-8 in March 2014, supplanted the error-prone legacy date-time API. Since then, it has been strongly recommended to use this modern date-time API.

Solution using modern date-time API

Convert your java.util.Date instance to java.time.Instant and subtract hours using Instant#minus.

Demo:

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        Date date = new Date(); // A sample java.util.Date
        Instant instant = date.toInstant();
        Instant updated = instant.minus(3, ChronoUnit.HOURS); // Subtracting 3 hours
        System.out.println(updated);
    }
}

Output:

2022-12-02T07:13:10.426Z

For any reason, if you want to get java.util.Date again, you can do so by using Date#from.

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110