如何在Java中找到一年中的总周数?

Kum*_*mal 10 java date week-number java-8

我正在做一个项目。在那里我应该找到一年的总周数。我尝试使用以下代码,但得到错误答案: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;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

输出:

52

Swe*_*per 6

此处使用 Wikipedia 定义。如果 1 月 1 日是星期四,则一年有 53 周,或者 12 月 31 日是星期四,否则一年有 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;
Run Code Online (Sandbox Code Playgroud)


Bas*_*que 6

tl;博士

对于标准 ISO 8601 周,使用ThreeTen-Extra库中的YearWeek类和三元语句。

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. 
Run Code Online (Sandbox Code Playgroud)

那是, YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52

定义“周”

您需要定义一周。在您的代码示例中,周的定义因 JVM 的当前默认值而异Locale。因此,您的结果可能会在运行时有所不同。

您的代码还使用了多年前被现代java.time类取代的糟糕的日期时间类。停止使用GregorianCalendar& Calendar; 他们被替换是有充分理由的。

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 ;
Run Code Online (Sandbox Code Playgroud)

要询问特定的基于周的年份,只需任意选择一年中的任何一周。例如,对于基于周的 2020 年,我们要求第 1 周。

int weeksLong = YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52 ;
LocalDate weekStart = YearWeek.of( 2020 , 1 ).atDay( DayOfWeek.MONDAY ) ;
Run Code Online (Sandbox Code Playgroud)

周长 = 53

周开始 = 2019-12-30

请注意 2020 年基于周的年份的第一天与 2019 日历年的关系。