Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find total weeks of a year in Java?

I am working on a project. There I should find the total weeks of a year. I tried with the following code, but I get the wrong answer: 2020 has 53 weeks, but this code gives 52 weeks.

Where have I gone wrong in this code?

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

    }

}

Output:

52

like image 328
Kumaresan Perumal Avatar asked Jan 27 '20 17:01

Kumaresan Perumal


People also ask

How do you calculate the number of weeks in a year?

To know how many weeks there are in a year, you just divide the number of days there are in a year (365) by how many days there are in a week (7). The result will be the average number of weeks there are in a year, which is approximately 52.143, or 52 weeks plus 1 day.

How do you calculate remaining weeks in Java?

Now we can use the ChronoUnit enum to calculate elapsed weeks. long weeks = ChronoUnit. WEEKS. between( startZdt , stopZdt );

What is week based year in Java?

Week number 1 has the first Thursday of the new calendar year. This definition means week-based year has either 52 or 53 whole weeks, always 7-days long (Monday-Sunday),for a year length of either 364 days or 371 days. In contrast, a calendar year has either 365 or 366 days crossing 52 partial weeks.

How to convert days to years and weeks in Java?

Days to years (ignoring leap year) and weeks conversion formula is expressed as: 1 year = 365 days 1 week = 7 days Using above formula we can construct our Java expression to convert days to years, weeks and days. years = days / 365; weeks = (days - (years * 365)) / 7; days = days - ((years * 365) + (weeks * 7));

How to calculate total years and weeks in Excel?

Divide number of days with 365 to get total years i.e. years = days / 365;. Next, we will find remaining weeks. To find remaining weeks, divide remaining days after calculated years by 7, say weeks = (days - (years * 365)) / 7;. You can also use a simple approach i.e. weeks = (days % 365) / 7;.

How to get a year from date in Java?

There are many ways to get a year from date of which frequently used two methods are listed below. Let us discuss each of them in detail alongside implementing the methods The get () method of LocalDate class in Java method gets the value of the specified field from this Date as an int.

How to get week number from local date in Java 8?

LocalDate date = LocalDate.of (year, month, day); int weekOfYear = date.get (WeekFields.of (locale).weekOfYear ()); The benefit over our pre-Java 8 examples is that we don't have the problem of the month field being zero-based. 3.2. Get Week Number Using Chronofield


4 Answers

The flexible solution

This should work for any week numbering scheme that can be represented in a WeekFields object.

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

The idea is to find the week number of the last week of the week based year. I try first with 31 December, but that may be in the first week of the following year. If so, I go one week back.

I have tested pretty thoroughly with WeekFields.ISO, not so much with other WeekFields objects, but as I said, I believe it works.

If you know for a fact that you will always need ISO 8601 weeks, I think you should go with one of the good answers by Sweeper and by Basil Bourque. I posted this in case you needed a more flexible solution that would work with other week numbering schemes too.

Use java.time

The code in your question is funny in that it imports classes both from Joda-Time and from java.time, yet uses the old Calendar and GregorianCalendar from Java 1.1. These classes were poorly designed and are now long outdated, you should not use them. Joda-Time is in maintenance mode, java.time has taken over after it. Which is what I use and recommend that you use.

like image 85
Ole V.V. Avatar answered Oct 18 '22 22:10

Ole V.V.


Using the Wikipedia definition here. A year has 53 weeks if 1st Jan is a Thursday, or 31st Dec is a Thursday, otherwise it has 52 weeks. This definition is equivalent to the one you used. I think this is a way easier condition to check for, as you don't need to check for leap years.

Using the Java 8 java.time APIs:

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;
like image 33
Sweeper Avatar answered Oct 18 '22 22:10

Sweeper


tl;dr

For a standard ISO 8601 week, use the YearWeek class from ThreeTen-Extra library with a ternary statement.

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. 

That is, YearWeek.of( 2020 , 1 ).is53WeekYear() ? 53 : 52

Define “week”

You need to define a week. In your code sample, the definition of week varies by the JVM’s current default Locale. So your results may vary at runtime.

Your code also uses terrible date-time classes that were supplanted years ago by the modern java.time classes. Stop using GregorianCalendar & Calendar; they were replaced for good reasons.

ISO 8601 week

The ISO 8601 standard defines a week as:

  • Weeks start on Monday, end on Sunday.
  • Week # 1 has the first Thursday of the calendar-year.

That definition means:

  • The first and last few days of a week-based-year may be the trailing/leading days of the previous/following calendar-year.
  • The week-based-year has either 52 or 53 complete weeks.

If your definition differs, see the Answer by Ole V.V..

YearWeek:is53WeekYear

If this matches your definition, then add the ThreeTen-Extra library to your project to extend the java.time functionality built into Java 8 and later. You then have access to the YearWeek class.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
YearWeek yearWeekNow = YearWeek.now( z ) ;
boolean is53WeekYear = yearWeekNow.is53WeekYear() ;

int weeksLong = yearWeekNow.is53WeekYear() ? 53 : 52 ;

To ask about a particular week-based-year, just arbitrarily pick any week of the year. For example, for the week-based year 2020 we ask for week # 1.

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

weeksLong = 53

weekStart = 2019-12-30

Notice how the first day of the week-based-year of 2020 is from the calendar-year 2019.

like image 6
Basil Bourque Avatar answered Oct 18 '22 22:10

Basil Bourque


I think this should work just fine as well:

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);
like image 1
Tim Hunter Avatar answered Oct 18 '22 20:10

Tim Hunter