Nuñito Calzada
Nuñito Calzada

Reputation: 2136

Java 8 substract dates but keep the hour

I want to subtract 7 days from Now, but keeping the time, so If now is 12/09/2018 at 18:30, get 05/09/2018 at 18:30...

I've tried:

public static Date subtractDays (int numDaysToSubstract) {
        LocalDate now = LocalDate.now().minusDays(numDaysToSubstract); 
        return Date.from(now.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

But I got 05/09/2018 at 00:00

Upvotes: 1

Views: 304

Answers (5)

Anonymous
Anonymous

Reputation: 86324

It’s unclear from the code in the other answers posted until now how they handle summer time (DST) and other time anomalies. And they do that differently. To make it clearer that you want 18.30 last week if time now is 18.30, no matter if a transition to or from summer time has happened in the meantime I suggest using ZonedDateTime:

    System.out.println("Now:                 " + Instant.now());
    Instant aWeekAgo = ZonedDateTime.now(ZoneId.of("Europe/Madrid"))
            .minusWeeks(1)
            .toInstant();
    System.out.println("A week ago in Spain: " + aWeekAgo);

Since summer time in Spain hasn’t ended or begun within the last week, running the code snippet just now gave the same time of day also in UTC (which is what Instant prints):

Now:                 2018-09-13T09:46:58.066957Z
A week ago in Spain: 2018-09-06T09:46:58.102680Z

I trust you to adapt the idea to your code.

Upvotes: 1

Mani Shankar
Mani Shankar

Reputation: 11

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Test {

    public static String subtractDays (int numDaysToSubstract) {
        LocalDateTime now = LocalDateTime.now().minusDays(numDaysToSubstract);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        String formatDateTime = now.format(formatter);


        return formatDateTime;
    }
    public static void main(String[] args){

        System.out.println(subtractDays(7));

    }
}

Upvotes: -1

Savior
Savior

Reputation: 3531

As others have suggested, LocalDate and atStartOfDay should have been red flags based on just their name. They are the wrong type to describe a time and the wrong method to maintain the time.

It's also kind of pointless to go through LocalDateTime to then convert it to an Instant. Just use an Instant straight up

public static Date subtractDays(int numDaysToSubstract) {
    return Date.from(Instant.now().minus(numDaysToSubstract, ChronoUnit.DAYS));
    // or
    // return Date.from(Instant.now().minus(Duration.ofDays(numDaysToSubstract)));

}

(I assume you're using java.util.Date because of compatibility with some old API.)

Upvotes: 3

Olivier Boissé
Olivier Boissé

Reputation: 18143

You should use LocalDateTime instead of LocalDate

LocalDate is just a description of the date without time or time-zone

public static Date subtractDays (int numDaysToSubstract) {
    LocalDateTime now = LocalDateTime.now().minusDays(numDaysToSubstract); 
    return Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
}

Upvotes: 0

Tom Bunting
Tom Bunting

Reputation: 1875

Use class LocalDateTime instead of LocalDate (which doesn't contain a time component..)

Upvotes: 0

Related Questions