Pracuję nad projektem. Tam powinienem znaleźć całkowitą liczbę tygodni w roku. Próbowałem z następującym kodem, ale otrzymałem złą odpowiedź: 2020 ma 53 tygodnie, ale ten kod daje 52 tygodnie.
Gdzie popełniłem błąd w tym kodzie?
package com.hib.mapping;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.joda.time.DateTime;
public class TestWeek {
public static void main(String args[]) {
System.out.println(getWeeks());
}
public static int getWeeks() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2020);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
GregorianCalendar gregorianCalendar = new GregorianCalendar();
int weekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (gregorianCalendar.isLeapYear(2020)) {
if (weekDay == Calendar.THURSDAY || weekDay == Calendar.WEDNESDAY)
return 53;
else
return 52;
} else {
if (weekDay == Calendar.THURSDAY)
return 53;
else
return 52;
}
}
}
Wynik:
52
java
date
java-8
week-number
Kumaresan Perumal
źródło
źródło
Date
iCalendar
. Użyjjava.time
zamiast tego, jest znacznie lepszy i prostszy.Odpowiedzi:
Korzystając z definicji Wikipedii tutaj . Rok ma 53 tygodnie, jeśli 1 stycznia jest czwartkiem lub 31 grudnia czwartkiem, w przeciwnym razie ma 52 tygodnie. Ta definicja jest równoważna definicji, której użyłeś. Myślę, że jest to o wiele łatwiejszy warunek do sprawdzenia, ponieważ nie musisz sprawdzać przez lata przestępne.
Korzystanie z
java.time
interfejsów API Java 8 :źródło
tl; dr
W przypadku standardowego tygodnia ISO 8601 użyj
YearWeek
klasy od biblioteki ThreeTen-Extra z instrukcją potrójną.To jest,
YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52
Zdefiniuj „tydzień”
Musisz zdefiniować tydzień. W przykładowym kodzie definicja tygodnia różni się w zależności od bieżącej wartości domyślnej maszyny JVM
Locale
. Dlatego wyniki mogą się różnić w czasie wykonywania.Twój kod używa również strasznych klas daty i czasu, które zostały zastąpione wiele lat temu przez nowoczesne klasy java.time . Przestań używać
GregorianCalendar
&Calendar
; zostały zastąpione z dobrych powodów.ISO 8601 tydzień
ISO 8601 norma definiuje tydzień jako:
Ta definicja oznacza:
Jeśli twoja definicja jest inna, zobacz odpowiedź Ole VV .
YearWeek:is53WeekYear
Jeśli jest to zgodne z definicją, dodaj bibliotekę ThreeTen-Extra do swojego projektu, aby rozszerzyć funkcjonalność java.time wbudowaną w Javę 8 i nowsze wersje . Masz wtedy dostęp do
YearWeek
klasy.Aby zapytać o konkretny rok, wystarczy arbitralnie wybrać dowolny tydzień w roku. Na przykład w roku 2020 na tydzień prosimy o tydzień nr 1.
Zwróć uwagę, jaki jest pierwszy dzień roku 2020 na podstawie tygodnia od roku kalendarzowego 2019.
źródło
now
. Ponieważ chcesz, aby liczba tygodni dla konkretnego roku była wyświetlana zamiast bieżącego, po prostu użyjYearWeek.of(yourYear, 1)
.Asia/Kolkata
, obecnie z przesunięciem +05: 30. W kodzie Java:ZoneId.of( "Asia/Kolkata" )
. Aby uzyskać więcej informacji i historii, zobacz Wikipedia, Czas w Indiach .Elastyczne rozwiązanie
Powinno to działać dla każdego schematu numeracji tygodni, który może być reprezentowany w
WeekFields
obiekcie.Chodzi o to, aby znaleźć numer tygodnia ostatniego tygodnia roku opartego na tygodniu. Najpierw próbuję z 31 grudnia, ale może to być w pierwszym tygodniu następnego roku. Jeśli tak, wracam tydzień wcześniej.
Testowałem dość dokładnie z
WeekFields.ISO
innymiWeekFields
przedmiotami, ale nie tak bardzo z innymi przedmiotami, ale jak powiedziałem, wierzę, że to działa.Jeśli wiesz na pewno, że zawsze będziesz potrzebować tygodni ISO 8601 , myślę, że powinieneś wybrać jedną z dobrych odpowiedzi Sweeper i Basil Bourque . Wysłałem to na wypadek, gdybyś potrzebował bardziej elastycznego rozwiązania, które działałoby również z innymi schematami numeracji tygodni.
Użyj java.time
Kod w twoim pytaniu jest zabawny, ponieważ importuje klasy zarówno z Joda-Time, jak i z java.time, ale używa starej
Calendar
iGregorianCalendar
z Java 1.1. Klasy te zostały źle zaprojektowane i są już dawno przestarzałe, nie należy ich używać. Joda-Time jest w trybie konserwacji, java.time przejął po nim. Tego używam i polecam.źródło
Myślę, że to też powinno działać dobrze:
źródło
Po wielu próbach w Javie 8. nie mogłem znaleźć rozwiązania. potem przygotowałem zależność Jody od daty i godziny. Dał mi dobrą odpowiedź, jak się spodziewałem
kod:
Zależność Maven:
źródło