2016-03-22 10 views
5

Entschuldigung im Voraus, wenn ich irgendwelche ISO Datumsangaben hier verwechsle.Wie kann ich jede Woche in einem Jahr in Java 8 iterieren?

Ich würde gerne in der Lage sein, jede Woche in einem bestimmten Jahr zu wiederholen (sagen wir 2015). Ich weiß, dass Sie die Anzahl der Wochen zwischen dem 1.1.2015 und dem 31.12.2015 berechnen können, aber das entspricht nicht dem ISO-Standard einer Woche. Vielmehr gibt es die Anzahl der 7-Tage-Perioden zwischen zwei Daten. Die erste ISO-Woche des Jahres beginnt nicht unbedingt am 1.1.2015.

Wenn ich das erste Datum der ersten Woche bekommen kann, glaube ich, ich kann einfach über ZonedDateTime.plusWeeks(1) für 52 Wochen iterieren. Sie können die Wochennummer eines beliebigen Datum über das Feld Accessor erhalten:

ZonedDateTime date = ZonedDateTime.now(); 
WeekFields weekFields = WeekFields.of(Locale.getDefault()); 
int weekNumber = date.get(weekFields.weekOfWeekBasedYear()); 

diese Gegeben, ich glaube, es möglich sein muss, das Datum des ersten Tages der ersten Woche eines spezifischen zu erhalten Jahr in der Java8 Time API, aber ich habe noch keinen Weg gefunden, es zu tun.

+0

Siehe auch [meine Beispiele] (http://time4j.net/tutorial/appendix.html#x14) zum Erstellen eines ISO-Wochendatums in verschiedenen Bibliotheken. Selbst das alte JDK mit 'java.util.GregorianCalendar' ist anscheinend einfacher, weil JSR-310 (java.time-package) hier keine einfache Factory-Methode hat. –

Antwort

4

Sie können ein Datum konstruieren und an den ersten Tag der Woche für die erste Woche des Jahres einstellen mit den folgenden:

int year = 2016; 
WeekFields weekFields = WeekFields.ISO; 
LocalDate date = LocalDate.now().with(weekFields.weekBasedYear(), year) 
           .with(weekFields.weekOfWeekBasedYear(), 1) 
           .with(ChronoField.DAY_OF_WEEK, 1); 

Dank JodaStephen ‚s Kommentar, auf eine andere Art und Weise zu setzen, es wäre die IsoFields Klasse zu verwenden.

LocalDate date = LocalDate.now().with(IsoFields.WEEK_BASED_YEAR, year) 
           .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1) 
           .with(ChronoField.DAY_OF_WEEK, 1); 

WeekFields.ISO stellt die ISO-Definition der Woche:

Die ISO-8601-Definition, wo eine Woche am Montag beginnt, und die erste Woche mindestens 4 Tage.

Der ISO-8601-Standard definiert ein Kalendersystem basierend auf Wochen. Es verwendet die Wochen- und Wochenkonfigurationen, um die Passage von Tagen anstelle von Standardjahr/Monat/Tag aufzuteilen.

Beachten Sie, dass die erste Woche im vorherigen Kalenderjahr beginnen kann. Beachten Sie auch, dass die ersten Tage eines Kalenderjahres dem Kalenderjahr entsprechen können, das dem Kalenderjahr entspricht.

Von dieser Definition können Sie erhalten:

  • weekBasedYear() stellt die Woche basierte Jahresfeld:

    Das Konzept des Jahres darstellt, wo Wochen auf einem festen Start Wochentag, wie Montag und jede Woche gehört genau zu einem Jahr.

    In diesem Fall möchten wir es auf das gewünschte Jahr setzen.

  • weekOfWeekBasedYear() stellt die Woche von Woche-Basis-Jahr

    Dieses Konzept der Zählung von Wochen im Jahr darstellt, wo Wochen an einem bestimmten Tag-of-Woche beginnen, wie Montag und jedem Die Woche gehört genau einem Jahr.

    In diesem Fall wollen wir die erste Woche der Woche-Basis-Jahr so ​​haben wir es auf 1

  • ChronoField.DAY_OF_WEEK, die den Tag der Woche darstellt. In diesem Fall wollen wir den ersten Tag der Woche so wir 1 gesetzt

Dann mit einem solchen Zeitpunkt, können Sie in der Tat alle Wochen des Jahres iterieren durch LocalDate.plusWeeks(1) Aufruf. Die Frage ist: Wie oft müssen Sie iterieren? Es kann mehr als 52 Wochen pro Jahr geben. Es gibt entweder 52 oder 53 Wochen pro Woche.

Sie können die Anzahl der Wochen mit dem folgenden abrufen. Rufen Sie rangeRefinedBy(date) auf, um die gültigen Werte des Felds Woche des Jahres für das angegebene Datum abzurufen und sein Maximum zu erhalten.

long maxWeekOfYear = weekFields.weekOfWeekBasedYear().rangeRefinedBy(date).getMaximum(); 
+0

Sie brauchen' weekOfWeaseBasedYear() 'und' weekBasedYear() '' not ' weekOfYear() 'und' dayOfWeek() '. Die zwei sind verschieden. In diesem Fall wäre es jedoch sinnvoller, 'IsoFields.WEEK_OF_WEEK_BASED_YEAR' und' IsoFields.WEEK_BASED_YEAR' zu verwenden, um die Verwirrung zu vermeiden. – JodaStephen

+0

@JodaStephen Können Sie ein wenig erweitern? Ich testete mit dem Jahr 2010 bis 2020 und das Ergebnis schien korrekt, aber ich gebe zu, manchmal Probleme mit all diesen Definitionen zu haben :) (und ich wusste nicht, dass "IsoFields" überhaupt existierte ...). – Tunaki

+1

'weekOfYear()' operiert innerhalb eines Kalenderjahres. 'weekOfWeekBasedYear()' operiert innerhalb einer 'weekBasedYear()' (der erste Tag eines wochenbasierten Jahres könnte im vorherigen Kalenderjahr liegen und der letzte Tag könnte im nächsten Kalenderjahr liegen). Da das OP nach ISO-Wochenjahren fragt, benötigen Sie die Wochen-basierten-Jahr-Methoden. – JodaStephen