2017-11-13 43 views
8

Mam metodę wyświetlania kalendarza w języku Java, która oblicza datę po roku, dzień tygodnia i numer tygodnia.Nieoczekiwany wynik obliczania daty

Teraz, gdy obliczam daty z 2017 roku, wszystko działa. Ale kiedy oblicza daty od stycznia 2018 zajmuje daty roku 2017

Mój kod wygląda

import java.time.temporal.IsoFields; 
import java.time.temporal.ChronoField; 
import java.time.LocalDate; 

// ..... 

LocalDate desiredDate = LocalDate.now() 
        .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1) 
        .with(ChronoField.DAY_OF_WEEK, 1) 
        .withYear(2018); 

co skutkuje 2018-01-02 i 2018-01-01 powinno być. Jak to jest możliwe?

+0

Może indeks dayOfWeek zaczyna się od 0 –

+0

NA Javadoc z ChronoFIeld ona mówi: Poniedziałek (1) do niedzieli (7) – JimmyD

+0

@SayanSil a) nie ma, i b) nie wyjaśnia wyniku "2018-01-02' – eis

Odpowiedz

12

Kolejność wywoływanych metod wydaje się mieć znaczenie.
on wywołać je malejąco czasowe ziarnistości (rok, tydzień tygodnia i dnia tygodnia), można uzyskać poprawny wynik:

long weekNumber = 1; 
long dayOfWeek = 1; 
int year = 2018; 

LocalDate desiredDate = LocalDate.now() 
    .withYear(year) 
    .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber) 
    .with(ChronoField.DAY_OF_WEEK, dayOfWeek); 

System.out.println(desiredDate); 

2018-01-01

Note że pochodzenie problem wynika z:

.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber) 

który wyznacza numer tygodnia (1 to 53) według bieżącego roku.
API Java LocalDate API nie może dostosować tej wartości, jeśli zmienisz rok z .withYear(year), ponieważ informacje o liczbie tygodni nie są przechowywane w instancji LocalDate.

można rzeczywiście zobaczyć w LocalDate realizacji że LocalDate przypadki są określone tylko przez 3 pola: year, month i day.

public final class LocalDate 
     implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable { 
    ... 
    private final int year; 
    /** 
    * The month-of-year. 
    */ 
    private final short month; 
    /** 
    * The day-of-month. 
    */ 
    private final short day; 
    ... 
} 

Więc być precyzyjny, ważną rzeczą jest to, że:

.withYear(year) być powoływane przed

.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber); 
+0

Tnx, który wykonał zadanie. – JimmyD

+2

ma sens - metody dopasowują poprzedni wynik, nie są oceniane w tym samym czasie. Ale mogę zrozumieć, że ktoś został zaskoczony przez to. – eis

+1

@davidxxx oryginalna wersja dostosowuje się do pierwszego poniedziałku 2017 (2 stycznia), a następnie zmienia rok. – assylias