프로젝트를 진행 중입니다. 거기에서 나는 일년의 총 주를 찾아야한다. 다음 코드로 시도했지만 틀린 답변을 얻습니다. 2020 년 53 주이지만이 코드는 52 주입니다.
이 코드에서 어디에서 잘못 되었습니까?
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;
}
}
}
산출:
52
답변
위키 백과의 정의를 사용하여 여기에 . 1 월 1 일이 목요일이거나 12 월 31 일이 목요일이면 1 년에 53 주가, 그렇지 않으면 52 주가 있습니다. 이 정의는 사용한 것과 동일합니다. 윤년을 확인할 필요가 없기 때문에 확인하기 쉬운 방법이라고 생각합니다.
Java 8 java.time
API 사용 :
int year = 2020;
boolean is53weekYear = LocalDate.of(year, 1, 1).getDayOfWeek() == DayOfWeek.THURSDAY ||
LocalDate.of(year, 12, 31).getDayOfWeek() == DayOfWeek.THURSDAY;
int weekCount = is53weekYear ? 53 : 52;
답변
tl; dr
표준 ISO 8601 주간의 경우 ThreeTen-Extra 라이브러리 의 YearWeek
클래스를 3 진 명령문과 함께 사용하십시오 .
YearWeek // Represents an entire week of a week-based-year.
.of( 2020 , 1 ) // Pass the number of the week-based-year (*not* calendar year), and a week number ranging from 1 to 52 or 1 to 53.
.is53WeekYear() // Every standard week-based-year has either 52 or 52 complete weeks.
? 53 // Ternary statement returns 53 if the predicate returns True, …
: 52 // … otherwise returns 52.
그건, YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52
“주”정의
일주일을 정의해야합니다. 코드 샘플에서 week 정의는 JVM의 현재 기본값에 따라 다릅니다 Locale
. 따라서 결과는 런타임에 달라질 수 있습니다.
코드는 또한 현대 java.time 클래스에 의해 몇 년 전에 대체 된 끔찍한 날짜-시간 클래스를 사용합니다 . 사용 중지 GregorianCalendar
및 Calendar
; 그들은 좋은 이유로 교체되었습니다.
ISO 8601 주
- 주는 월요일에 시작하여 일요일 에 끝납니다.
- 1 주차 에는 역년 의 첫 번째 목요일 이 있습니다.
그 정의는 다음을 의미합니다.
- 주 기반 연도의 첫 번째 및 마지막 며칠은 전 / 후 달력 연도의 후행 일일 수 있습니다.
- 주별 연도는 52 주 또는 53 주입니다.
YearWeek:is53WeekYear
이것이 정의와 일치하면 ThreeTen-Extra 라이브러리를 프로젝트에 추가 하여 Java 8 이상에 내장 된 java.time 기능 을 확장하십시오 . 그런 다음 YearWeek
수업에 액세스 할 수 있습니다 .
ZoneId z = ZoneId.of( "America/Montreal" ) ;
YearWeek yearWeekNow = YearWeek.now( z ) ;
boolean is53WeekYear = yearWeekNow.is53WeekYear() ;
int weeksLong = yearWeekNow.is53WeekYear() ? 53 : 52 ;
특정 주별 연도에 대해 질문하려면 연중 아무 주나 임의로 선택하십시오. 예를 들어 2020 년 주별 1 주를 요청합니다.
int weeksLong = YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52 ;
LocalDate weekStart = YearWeek.of( 2020 , 1 ).atDay( DayOfWeek.MONDAY ) ;
긴 주 = 53
weekStart = 2019-12-30
2020 년의 주별 첫날이 2019 년과 어떻게 다른지 확인하십시오.
답변
유연한 솔루션
이것은 WeekFields
객체 로 표현할 수있는 모든 주 번호 체계에 적용 됩니다.
public static int noOfWeeks(WeekFields wf, int year) {
LocalDate lastDayOfYear = YearMonth.of(year, Month.DECEMBER).atEndOfMonth();
if (lastDayOfYear.get(wf.weekBasedYear()) > year) { // belongs to following week year
return lastDayOfYear.minusWeeks(1).get(wf.weekOfWeekBasedYear());
}
else {
return lastDayOfYear.get(wf.weekOfWeekBasedYear());
}
}
아이디어는 주를 기준으로 마지막주의 주 번호를 찾는 것입니다. 12 월 31 일부터 시작하지만 다음 해의 첫 주에있을 수 있습니다. 그렇다면 1 주일 전으로 돌아갑니다.
나는 WeekFields.ISO
다른 WeekFields
객체 들과는 달리 꽤 철저히 테스트 했지만, 내가 말했듯이 그것이 효과가 있다고 생각합니다.
항상 ISO 8601 주가 필요하다는 사실을 알고 있다면 스위퍼 와 바실 부르크 의 좋은 답변 중 하나를 선택해야한다고 생각합니다 . 다른 주 번호 매기기 체계와 함께 작동하는보다 유연한 솔루션이 필요한 경우에 이것을 게시했습니다.
java.time 사용
질문의 코드는 Joda-Time과 java.time에서 클래스를 가져 오지만 이전 Calendar
과 GregorianCalendar
Java 1.1에서 클래스를 가져 오는 점에서 재미 있습니다. 이 클래스는 제대로 설계되지 않았으며 오래되어 오래되었습니다. 사용해서는 안됩니다. Joda-Time이 유지 보수 모드에 있으며 java.time이 그 이후에 인수되었습니다. 어느 것이 내가 사용하고 추천합니다.
답변
나는 이것이 잘 작동해야한다고 생각한다.
int year = 2020;
long numOfWeeks = LocalDate.of(year, 1, 1).datesUntil(LocalDate.of(year, 12, 31), Period.ofDays(7)).count();
System.out.println("Weeks: " + numOfWeeks);
답변
Java 8에서 많은 것을 시도한 후에 해결책을 찾을 수 없습니다. 그런 다음 Joda 날짜 및 시간 종속성을 준비했습니다. 예상대로 좋은 대답을 했어요
암호:
for (int i = 2020; i < 2100; i++) {
int weeks = new DateTime().withYear(i).weekOfWeekyear().getMaximumValue();
System.out.println(i + " years : " + weeks);
}
메이븐 의존성 :
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.5</version>
</dependency>