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

如何在Java中查找一年中的总周数?,java,date,java-8,week-number,Java,Date,Java 8,Week Number,我正在做一个项目。在那里我可以找到一年中的总周数。我尝试了以下代码,但得到了错误的答案: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.t

我正在做一个项目。在那里我可以找到一年中的总周数。我尝试了以下代码,但得到了错误的答案: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日是星期四,那么一年有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;

我认为这也应该很好:

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

在Java8中尝试了很多之后。我找不到解决办法。然后我准备了Joda日期和时间依赖项。正如我所料,它给了我一个很好的答案

代码:

for (int i = 2020; i < 2100; i++) {
  int weeks = new DateTime().withYear(i).weekOfWeekyear().getMaximumValue();
  System.out.println(i + " years : " + weeks); 
}
for(int i=2020;i<2100;i++){
int weeks=new DateTime().withYear(i).weekOfWeekyear().getMaximumValue();
系统输出打印项次(i+“年:”+周);
}
Maven依赖项:

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.10.5</version>
</dependency>

乔达时间
乔达时间
2.10.5
tl;博士 对于标准ISO 8601周,使用ThreeTen Extra library的
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. 
也就是说,
YearWeek.of(2020,1).is53WeekYear()?53:52

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

您的代码还使用了可怕的日期时间类,这些类在几年前被现代java.time类所取代。停止使用
gregorianalendar
Calendar
;他们被替换是有充分理由的

ISO 8601每周 标准如下:

  • 从周一开始,周日结束
  • 第1周是日历年的第一个星期四
该定义意味着:

  • 基于周的一年的前几天和最后几天可能是上一个/下一个日历年的最后几天
  • 基于周的年份有52或53个完整周
如果您的定义不同,请参阅

YearWeek:is53WeekYear
如果这与您的定义相匹配,那么将该库添加到您的项目中,以扩展java 8及更高版本中内置的java.time功能。然后您就可以访问该类

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

周长=53

周开始=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日,但那可能是在次年的第一周。如果是这样的话,我会回到一周前

我已经用
WeekFields.ISO
进行了非常彻底的测试,而不是用其他
WeekFields
对象,但正如我所说的,我相信它是有效的

如果你知道你总是需要几周的时间,我认为你应该给出一个好的答案和答案。我发布了这篇文章,以防您需要一个更灵活的解决方案,该解决方案也适用于其他周编号方案

使用java.time
您问题中的代码很有趣,因为它从Joda Time和java.Time导入类,但使用java 1.1中旧的
Calendar
GregoriaCalendar
。这些类设计得很糟糕,现在已经过时很久了,您不应该使用它们。Joda Time处于维护模式,java.Time在此之后接管。这就是我所使用的,并建议您使用。

下面的代码适合我。

public static int getTotalWeeksInYear(int year){
        int totalWeeks=0;
        Calendar calendar=Calendar.getInstance();
        for(int month=0;month<12;mmonth++){
            int day=1;
            do{
                calendar.set(year, month, day);
                if(calendar.get(Calendar.DAY_OF_WEEK)==5)
                    totalWeeks++;
                day++;
            }while (day <=calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        }
        return totalWeeks;
}

不完全是重复,但建议阅读:建议提供你对一周的定义。它是2020年。请避免在
日期
日历
周围使用麻烦的旧旧式日期api。改用
java.time
,它更好更简单。如果(年份是闰年)和(一月一日是星期日),那么54其他53。你能给我一些代码吗?一年中最长的一周53。我认为这很好@Naman没有54周,我认为正确的解决方案是LocalDate.of(I,1,1).range(WeekFields.ISO.weekOfWeekBasedYear()).getMaximum()它给出2021年53周的时间。我认为这是错误的。请测试it@KumaresanPerumal是的,它起作用了。我会用100年来测试然后告诉你。感谢您的努力,我已经在JDK 1.8.0_101和1.8.0_121上进行了测试。到2021年,我们还应该有52周的假期。真是个好主意。它给出了2020年(53周)以及2019年和2021年(各52周)的正确结果。不过,要说服自己可能有点困难。似乎所有闰年都有53周,这是不正确的。@OleV.V。嗯,很公平。我很好奇LocalDate的计算是如何工作的。愚蠢的地球,它的时间周期有点不完美,使事情变得更加复杂。是Java 9+我在印度。我应该指定国家名称吗?@KumaresanPerumal否,时区现在在那里。由于您希望获得特定年份的周数,而不是当前年份,只需使用
YearWeek.of(yourYear,1)
@KumaresanPerumal Wikipedia保留时区名称即可。可能有点过时了。据我所知,整个印度使用的时区是亚洲/加尔各答,目前偏移量为+05:30。在Java代码中:
ZoneId.of(“亚洲/加尔各答”)
。有关更多信息和历史,请参阅Wikipedia。我当然推荐java.time代码。与其说它更短,不如说它更容易理解。为什么不把它放在第一位呢?我也支持java.time。但在问题中,用户试图使用Calendar类解决问题。我真正想问的是什么问题
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());
    }
}
public static int getTotalWeeksInYear(int year){
        int totalWeeks=0;
        Calendar calendar=Calendar.getInstance();
        for(int month=0;month<12;mmonth++){
            int day=1;
            do{
                calendar.set(year, month, day);
                if(calendar.get(Calendar.DAY_OF_WEEK)==5)
                    totalWeeks++;
                day++;
            }while (day <=calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        }
        return totalWeeks;
}
public static long getTotalWeekByLocalDate(LocalDate ldate) {

        long weeksInYear = IsoFields.WEEK_OF_WEEK_BASED_YEAR.rangeRefinedBy(ldate).getMaximum();

        return weeksInYear;
    }