Jak odjąć dzień X od obiektu Date w Javie?

146

Chcę zrobić coś takiego:

Date date = new Date(); // current date
date = date - 300; // substract 300 days from current date and I want to use this "date"

Jak to zrobić?

yetAnotherSE
źródło
4
Obowiązkowa uwaga „Użyj czasu Joda”.
Steve McLeod
1
Poniższe linki mogą być przydatne dla Ciebie. [Wprowadź opis linku tutaj] [1] [wprowadź opis linku tutaj] [2] [1]: stackoverflow.com/questions/212321/… [2]: stackoverflow.com/questions/ 2623610 /…
Ami
FYI, kłopotliwe stare klasy daty i godziny, takie jak java.util.Dateobecnie starsze , zastąpione przez klasy java.time .
Basil Bourque

Odpowiedzi:

279

Java 8 i nowsze

Wraz ze zmianą interfejsu API daty i godziny Java 8 użyj LocalDate

LocalDate date = LocalDate.now().minusDays(300);

Podobnie możesz mieć

LocalDate date = someLocalDateInstance.minusDays(300);

Zobacz https://stackoverflow.com/a/23885950/260990, aby znaleźć tłumaczenie między java.util.Date <--> java.time.LocalDateTime

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

Java 7 i starsze

Wykorzystaniu koniecznie Calendar„S add()Sposób

Calendar cal = Calendar.getInstance();
cal.setTime(dateInstance);
cal.add(Calendar.DATE, -30);
Date dateBefore30Days = cal.getTime();
Jigar Joshi
źródło
22
Jest to ustawienie niestandardowej daty, na wypadek gdybyś nie chciał brać pod uwagę aktualnej daty i godziny
Jigar Joshi
11
Obsługa dat w Javie jest tak rozdęta!
digory doo
1
To jest odpowiedź od 4 lat. pojawiły się nowe zmiany w API DateTime w ostatnich wersjach.
Zmienię
FYI, kłopotliwego starych klas date-time, takie jak java.util.Date, java.util.Calendari java.text.SimpleTextFormatsą teraz spuścizny , wyparta przez java.time klas. Zobacz samouczek firmy Oracle .
Basil Bourque
@JigarJoshi byłoby wspaniale, gdybyś zaktualizował swoją odpowiedź za pomocą API Java 8. Twoja odpowiedź jest zaakceptowana, którą ludzie widzą jako pierwsza.
jotaen
47

@JigarJoshi to dobra odpowiedź i oczywiście @Tim zalecenie do użycia. czas joda .

Chcę tylko dodać więcej możliwości odejmowania dni od a java.util.Date.

Apache-commons

Jedną z możliwości jest użycie apache-commons-lang . Możesz to zrobić DateUtilsw następujący sposób:

Date dateBefore30Days = DateUtils.addDays(new Date(),-30);

Oczywiście dodaj commons-langzależność, aby robić tylko odejmowanie daty, prawdopodobnie nie jest to dobra opcja, jednak jeśli już używasz commons-lang, jest to dobry wybór. Istnieje również dogodne formy do addYears, addMonths, addWeeksi tak dalej, warto zapoznać się z API tutaj .

Java 8

Inną możliwością jest skorzystanie z nowości LocalDatez Java 8 przy użyciu minusDays(long days)metody:

LocalDate dateBefore30Days = LocalDate.now(ZoneId.of("Europe/Paris")).minusDays(30);
albciff
źródło
Nie ma sensu używać LocalDateTimetej klasy celowo, ponieważ nie ma pojęcia strefy czasowej ani przesunięcia względem UTC. Użyj tego tylko wtedy, gdy strefa / przesunięcie jest nieznane lub nieistotne. Zamiast tego użyj LocalDatei przekaż a ZoneIdpodczas wywoływania jego nowmetody. Zobacz poprawną odpowiedź Jacoba van Lingena.
Basil Bourque
1
@BasilBourque Po twojej radzie sprawdzam interfejs API i masz całkowitą rację, dlatego aktualizuję odpowiedź. dzięki.
albciff
Brian Montellano chciałby komentarza: nie powinno być żadnych sw DateUtils, to po prostu DateUtil.
Ole VV
@ OleV.V. Brian Montellano się myli, możesz sprawdzić DateUtilsdokumenty
albciff
33

Po prostu użyj tego, aby uzyskać datę sprzed 300 dni, zamień 300 na swoje dni:

Date date = new Date(); // Or where ever you get it from
Date daysAgo = new DateTime(date).minusDays(300).toDate();

Tutaj,

DateTime jest org.joda.time.DateTime;

Date jest java.util.Date

Tim
źródło
7
Projekt Joda-Time jest teraz w trybie konserwacji i zaleca migrację do klas java.time .
Basil Bourque
13

Java 8 Time API:

Instant now = Instant.now(); //current date
Instant before = now.minus(Duration.ofDays(300));
Date dateBefore = Date.from(before);
Grigorij Kislin
źródło
Muszę mieć na myśli API Java 8, a nie 7. Wspomnienie o pakiecie java.timemoże pomóc. Ponadto ogólnie oczekuje się dyskusji / wyjaśnień na temat przepełnienia stosu, a nie tylko fragmentu kodu. Zdecydowanie powinieneś to wyjaśnić, Durationponieważ jest to wartość dodana Twojej odpowiedzi w stosunku do istniejącej autorstwa van Lingena .
Basil Bourque
Przyczyna Java 8, naprawiona
Grigorij Kislin
tak blisko, ale powinno służyć do modyfikowania dowolnego obiektu daty, a nie „teraz”
bharal
9

Jak widać TUTAJ , jest wiele możliwości manipulacji. Oto przykład pokazujący, co możesz zrobić!

DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();

//Add one day to current date.
cal.add(Calendar.DATE, 1);
System.out.println(dateFormat.format(cal.getTime()));

//Substract one day to current date.
cal = Calendar.getInstance();
cal.add(Calendar.DATE, -1);
System.out.println(dateFormat.format(cal.getTime()));

/* Can be Calendar.DATE or
*  Calendar.MONTH, Calendar.YEAR, Calendar.HOUR, Calendar.SECOND
*/
waldyr.ar
źródło
@Jigar Joshi: Nie widziałem twojej odpowiedzi ... Czy mam usunąć swoją?
waldyr.ar
FYI, strasznie kłopotliwe stare klasy daty i godziny, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek firmy Oracle .
Basil Bourque
9

Dzięki Javie 8 jest to teraz naprawdę proste:

 LocalDate date = LocalDate.now().minusDays(300);

Świetny przewodnik po nowym interfejsie API można znaleźć tutaj .

Jacob van Lingen
źródło
4
Sugeruję zawsze przekazywanie opcjonalnej strefy czasowej (lub przesunięcia od UTC) do tej nowmetody. W przypadku pominięcia bieżąca domyślna strefa czasowa maszyny JVM jest stosowana niejawnie i dyskretnie. To ustawienie domyślne jest poza Twoją kontrolą i może ulec zmianie w dowolnym momencie, nawet podczas działania. Przykład: LocalDate.now( ZoneId.of( "America/Montreal" ).
Basil Bourque
musi znajdować się w obiekcie o dowolnej dacie zgodnie z pytaniem, a nie „teraz”
bharal
1

Stworzyłem funkcję ułatwiającą zadanie.

  • Przez 7 dni od daty Ciąg: dateCalculate(dateString,"yyyy-MM-dd",7);

  • Aby uzyskać aktualizację przez 7 dni, ciąg: dateCalculate(dateString,"yyyy-MM-dd",-7);


public static String dateCalculate(String dateString, String dateFormat, int days) {
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat s = new SimpleDateFormat(dateFormat);
    try {
        cal.setTime(s.parse(dateString));
    } catch (ParseException e) {
        e.printStackTrace();
    }
    cal.add(Calendar.DATE, days);
    return s.format(cal.getTime());
}
refleksgrawitacja
źródło
Ta odpowiedź zastosowania kłopotliwe starych klas Date-Time, takich jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatże są teraz Legacy , wyparta przez java.time klas. Zobacz samouczek firmy Oracle .
Basil Bourque
Pytanie dotyczy obiektów daty i godziny, a nie generowania ciągów. Nawiasem mówiąc, LocalDate.parse( "2017-01-23").plusWeeks( 1 )jest prostsze niż pisanie własnej metody i jest bardziej samodokumentujące.
Basil Bourque
0

Możesz łatwo odejmować za pomocą kalendarza z SimpleDateFormat

 public static String subtractDate(String time,int subtractDay) throws ParseException {


        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ENGLISH);
        cal.setTime(sdf.parse(time));
        cal.add(Calendar.DATE,-subtractDay);
        String wantedDate = sdf.format(cal.getTime());

        Log.d("tag",wantedDate);
        return wantedDate;

    }
Ucdemir
źródło
-4
c1.set(2017, 12 , 01); //Ex: 1999 jan 20    //System.out.println("Date is : " + sdf.format(c1.getTime()));
  c1.add(Calendar.MONTH, -2); // substract 1 month
  System.out.println
  ("Date minus 1 month : "
      + sdf.format(c1.getTime()));
Usama Iqbal
źródło
2
Witamy w SO. Proszę powstrzymać się od odpowiedzi tylko kodem. Zobacz stackoverflow.com/help/how-to-answer . I sformatuj swój kod.
Uwe Allner