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


11

프로젝트를 진행 중입니다. 거기에서 나는 일년의 총 주를 찾아야한다. 다음 코드로 시도했지만 틀린 답변을 얻습니다. 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
정확히 중복되지는 않았지만 제안 된 것 : stackoverflow.com/questions/44197872/…
Federico klez Culloca

1
일주일의 정의를 제안하십시오.
앤디

4
그것은 귀찮은 오래된 레거시 날짜 API를 주위를 사용하여 2020하시기 바랍니다 피하고있다 DateCalendar. java.time대신 사용 하는 것이 훨씬 좋고 간단합니다.
Zabuzard

(연도가 도약) 및 (1 월 1 일은 일요일) 54 일 경우 53.
Akina

코드 좀 주 시겠어요?
Kumaresan Perumal

답변:


7

위키 백과의 정의를 사용하여 여기에 . 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;

53 년의 최대 주 53. 나는 @ @ @ 54 주가 없다고 생각합니다, 올바른 해결책은 LocalDate.of (i, 1, 1) .range (WeekFields.ISO.weekOfWeekBasedYear ()). getMaximum ()
Kumaresan Perumal

1
그것은 2021 년에 53 주를줍니다. 나는 그것이 틀렸다고 생각합니다. 그것을 시험해주세요
Kumaresan Perumal

1
@KumaresanPerumal 확실합니까?
스위퍼

1
예, 작동합니다. 나는 100 년 동안 시험 한 다음 말해 줄 것이다.
노력해

1
JDK 1.8.0_101 및 1.8.0_121에서 테스트했습니다. 2021 년에는 여전히 52 주가 걸리고 있습니다.
Ole VV

7

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 년과 어떻게 다른지 확인하십시오.


나는 인도에있어. 국가 이름을 지정해야합니까?
Kumaresan Perumal

@KumaresanPerumal 아니요, 시간대는입니다 now. 현재 연도 대신 특정 연도의 주 수를 얻으려면을 사용하십시오 YearWeek.of(yourYear, 1).
스위퍼

알겠습니다 감사합니다 @ 스위퍼 사용하겠습니다
Kumaresan Perumal

@KumaresanPerumal Wikipedia는 시간대 이름 목록 을 유지 합니다. 약간 오래된 버전 일 수 있습니다. 내가 아는 한, 모든 인도는 시간대가입니다 Asia/Kolkata. 현재 오프셋은 +05 : 30입니다. Java 코드에서 : ZoneId.of( "Asia/Kolkata" ). 자세한 정보 및 기록은 Wikipedia, Time in India를 참조하십시오 .
바질 부르 케

4

유연한 솔루션

이것은 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이 그 이후에 인수되었습니다. 어느 것이 내가 사용하고 추천합니다.


1

나는 이것이 잘 작동해야한다고 생각한다.

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

좋은 생각이야 2019 년과 2021 년 (52 주)뿐만 아니라 2020 년 (53 주)에 대한 올바른 결과를 제공합니다. 그래도 자신을 설득하기는 조금 어려울 수 있습니다.
Ole VV

그러나 모든 윤년에는 53 주가 걸리는 것 같습니다.
Ole VV

@ OleV.V. 흠, 충분합니다. 그때 LocalDate의 계산이 어떻게 작동하는지 궁금합니다. 어리석은 지구와 시간이 약간 불완전하여 상황을 복잡하게 만듭니다.
팀 헌터

LocalDate.datesJava 9 이상이 될 때까지
ZhekaKozlov

0

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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.