[java] Java에서 일주일에 총 몇 주를 찾는 방법은 무엇입니까?

프로젝트를 진행 중입니다. 거기에서 나는 일년의 총 주를 찾아야한다. 다음 코드로 시도했지만 틀린 답변을 얻습니다. 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.timeAPI 사용 :

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 클래스에 의해 몇 년 전에 대체 된 끔찍한 날짜-시간 클래스를 사용합니다 . 사용 중지 GregorianCalendarCalendar; 그들은 좋은 이유로 교체되었습니다.

ISO 8601 주

ISO 8601 표준은 일주일에 정의 등을 :

  • 주는 월요일에 시작하여 일요일 에 끝납니다.
  • 1 주차 에는 역년 의 첫 번째 목요일 이 있습니다.

그 정의는 다음을 의미합니다.

  • 주 기반 연도의 첫 번째 및 마지막 며칠은 전 / 후 달력 연도의 후행 일일 수 있습니다.
  • 주별 연도는 52 주 또는 53 주입니다.

정의가 다르면 Ole VV답변을 참조하십시오 .

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에서 클래스를 가져 오지만 이전 CalendarGregorianCalendarJava 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>


답변