2017-11-13 6 views
8

Ich habe eine Methode, um einen Kalender in Java anzuzeigen, der das Datum nach Jahr, Wochentag und Wochennummer berechnet.Unerwartetes Datum Berechnungsergebnis

Jetzt, wenn ich die Daten von 2017 berechnet, funktioniert alles. Aber wenn ich die Termine von Januar 2018 berechnet nimmt es die Daten des Jahres 2017.

Mein Code sieht aus wie

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); 

die in 2018.01.02 führt und es sollte 2018.01.01 sein. Wie ist das möglich?

+0

es der dayOfWeek Index beginnt bei 0 –

+0

ON Javadoc des ChronoFIeld sagt vielleicht: Montag, (1) bis Sonntag (7) – JimmyD

+0

@SayanSil a) es nicht, und b) das würde das Ergebnis '2018-01-02' nicht erklären – eis

Antwort

12

Die Reihenfolge der aufgerufenen Methoden scheint von Bedeutung zu sein.
Es Sie sie aufrufen, indem zeit Granularität absteigend (Jahr, Woche der Woche und Wochentag), erhalten Sie das richtige Ergebnis:

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

Hinweis dass das Problem Ursprung stammt aus:

.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber) 

, die die Wochennummer (1 to 53) entsprechend dem laufenden Jahr setzt.
Die Java-API LocalDate kann diesen Wert nicht anpassen, wenn Sie das Jahr mit .withYear(year) ändern, da die Wochennummerninformationen nicht in der LocalDate Instanz gespeichert sind. sehen in der Tat

können Sie in LocalDate Implementierung dass LocalDate Instanzen von nur 3 Feld definiert sind: year, month und 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; 
    ... 
} 

So genau zu sein, das Wichtigste ist, dass:

.withYear(year) vor

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

Tnx, dass die Arbeit gemacht hat. – JimmyD

+2

macht Sinn - Methoden passen das vorherige Ergebnis an, sie werden nicht gleichzeitig ausgewertet. Aber ich kann jemanden verstehen, der dadurch überrascht wird. – eis

+1

@davidxxx die ursprüngliche Version stellt sich auf den ersten Montag von 2017 (2. Januar) dann ändert das Jahr. – assylias