Anton Smith
Anton Smith

Reputation: 365

Get the number of weeks between two Dates.

Im working in a project and I got two types in Date. I want to calculate the number of weeks between these two dates. The dates can be in diffrent years. Is there any good solution for this?

I have tried to implemenent this with Joda-time which was suggested in other topics..

Im not familar with this library, but I tried to do something like this:

public static int getNumberOfWeeks(Date f, Date l){
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.setTime(f);
    c2.setTime(l);
    DateTime start = new DateTime(c1.YEAR, c1.MONTH, c1.DAY_OF_MONTH, 0, 0, 0, 0);
    DateTime end   = new DateTime(c2.YEAR, c2.MONTH, c2.DAY_OF_MONTH, 0, 0, 0, 0);
    Interval interval = new Interval(start, end);
    Period p = interval.toPeriod();
    return p.getWeeks();
}

But this is completely wrong... any suggestions ?

Upvotes: 29

Views: 65565

Answers (19)

Yash Avlani
Yash Avlani

Reputation: 1

After referring many solution, this worked for me. {Provided I did not want to use external Libraries}

public static int getNumberOfWeeks(Date date1, Date date2) {
if (date1.after(date2)) {
        return getNumberOfWeeks(date2, date1);
    }

    Date date = date1;
    int days = 0;
    while (date.before(date2)) {
        days++;
        date = addDays(date, 1);
    }
    return days/7;
}

To add days to a date :

Date addDays(Date date, int days) {
    if (days == 0) {
        return date;
    } else {
        Date shiftedDate = new Date(date.getTime() + (long)days * 86400000L);
        return shiftedDate;
    }
}

Upvotes: 0

Rashid
Rashid

Reputation: 375

Here is a simple way to find the number of weeks between two dates.

SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String classStartData = "31 01 2021";
String classEndData = "08 03 2021";

Date dateClassStart = myFormat.parse(classStartData);
Date dateClassEnd = myFormat.parse(classEndData);

long differenceWeek = dateClassEnd.getTime() - dateClassStart.getTime();
int programLength = (int)(TimeUnit.DAYS.convert(differenceWeek, TimeUnit.MILLISECONDS)/7);
System.out.println("Class length in weeks: " +programLength);

Upvotes: 0

Jonathan Applebaum
Jonathan Applebaum

Reputation: 5986

Here are 2 methods I wrote that not based on an external library.
The first method is when Monday is the first day of the week.
The second method is when Sunday is the first day of the week.

Please read the comments inside the code, there is an option to return the number of the full weeks between 2 dates,
and also with the fraction of the remaining days before and after the 2 dates.

public static int getNumberOfFullWeeks(LocalDate startDate,LocalDate endDate)
{
    int dayBeforeStartOfWeek = 0;
    int daysAfterLastFullWeek = 0;

    if(startDate.getDayOfWeek() != DayOfWeek.MONDAY)
    {
        // get the partial value before loop starting
        dayBeforeStartOfWeek = 7-startDate.getDayOfWeek().getValue() + 1;
    }

    if(endDate.getDayOfWeek() != DayOfWeek.SUNDAY)
    {
        // get the partial value after loop ending
        daysAfterLastFullWeek = endDate.getDayOfWeek().getValue();
    }

    LocalDate d1 = startDate.plusDays(dayBeforeStartOfWeek); // now it is the first day of week;
    LocalDate d2 = endDate.minusDays(daysAfterLastFullWeek); // now it end in the last full week

    // Count how many days there are of full weeks that start on Mon and end in Sun
    // if the startDate and endDate are less than a full week the while loop
    // will not iterate at all because d1 and d2 will be the same date
    LocalDate looper = d1;
    int counter = 1;
    while (looper.isBefore(d2))
    {
        counter++;
        looper = looper.plusDays(1);
    }

    // Counter / 7 will always be an integer that will represents full week
    // because we started to count at Mon and stop counting in Sun
    int fullWeeks = counter / 7;

    System.out.println("Full weeks between dates: "
            + fullWeeks + " Days before the first monday: "
            + dayBeforeStartOfWeek + " "
            + " Days after the last sunday: " + daysAfterLastFullWeek);
    System.out.println(startDate.toString() + " - " + endDate.toString());

    // You can also get a decimal value of the full weeks plus the fraction if the days before
    // and after the full weeks
    float full_weeks_decimal = (float)fullWeeks;
    float fraction = ((float)dayBeforeStartOfWeek + (float)daysAfterLastFullWeek) / 7.0F;
    System.out.println("Full weeks with fraction: " + String.valueOf(fraction + full_weeks_decimal));

    return fullWeeks;
}

public static int getNumberOfFullWeeks_WeekStartAtSunday(LocalDate startDate,LocalDate endDate)
{
    int dayBeforeStartOfWeek = 0;
    int daysAfterLastFullWeek = 0;

    if(startDate.getDayOfWeek() != DayOfWeek.SUNDAY)
    {
        // get the partial value before loop starting
        dayBeforeStartOfWeek = 7-getDayOfWeekBySundayIs0(startDate.getDayOfWeek()) + 1;
    }

    if(endDate.getDayOfWeek() != DayOfWeek.SATURDAY)
    {
        // get the partial value after loop ending
        daysAfterLastFullWeek = 1+getDayOfWeekBySundayIs0(endDate.getDayOfWeek());
    }

    LocalDate d1 = startDate.plusDays(dayBeforeStartOfWeek); // now it is the first day of week;
    LocalDate d2 = endDate.minusDays(daysAfterLastFullWeek); // now it end in the last full week

    // Count how many days there are of full weeks that start on Sun and end in Sat
    // if the startDate and endDate are less than a full week the while loop
    // will not iterate at all because d1 and d2 will be the same date
    LocalDate looper = d1;
    int counter = 1;
    while (looper.isBefore(d2))
    {
        counter++;
        looper = looper.plusDays(1);
    }

    // Counter / 7 will always be an integer that will represents full week
    // because we started to count at Sun and stop counting in Sat
    int fullWeeks = counter / 7;

    System.out.println("Full weeks between dates: "
            + fullWeeks + " Days before the first sunday: "
            + dayBeforeStartOfWeek + " "
            + " Days after the last saturday: " + daysAfterLastFullWeek);
    System.out.println(startDate.toString() + " - " + endDate.toString());

    // You can also get a decimal value of the full weeks plus the fraction if the days before
    // and after the full weeks
    float full_weeks_decimal = (float)fullWeeks;
    float fraction = ((float)dayBeforeStartOfWeek + (float)daysAfterLastFullWeek) / 7.0F;
    System.out.println("Full weeks with fraction: " + String.valueOf(fraction + full_weeks_decimal));

    return fullWeeks;
}

   public static int getDayOfWeekBySundayIs0(DayOfWeek day)
    {
        if(day == DayOfWeek.SUNDAY)
        {
            return 0;
        }
        else
        {
            // NOTE: getValue() is starting to count from 1 and not from 0
            return  day.getValue();
        }
    }

Upvotes: 2

Dinith
Dinith

Reputation: 1

Easy way

  Calendar cal1 = new GregorianCalendar();
    Calendar cal2 = new GregorianCalendar();
    cal1.set(2014, 3, 3);
    cal2.set(2015, 3, 6);

    weekscount.setText("weeks= "+ ( (cal2.getTime().getTime() - cal1.getTime().getTime()) / (1000 * 60 * 60 * 24))/7);

Upvotes: 0

Basil Bourque
Basil Bourque

Reputation: 340098

tl;dr

ChronoUnit
.WEEKS
.between(
    myJavaUtilDate_Start.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) , 
    myJavaUtilDate_Stop.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) 
)

7

java.time

The java.time framework is built into Java 8 and later. These new classes supplant the old date-time classes bundled with the earliest versions of Java.

The java.time classes also supplant the highly successful Joda-Time framework. Both java.time and Joda-Time are led by Stephen Colbourne.

Table of date-time types in Java, both modern and legacy

Instant replaces java.util.Date

The modern class Instant replaces the legacy class java.util.Date. Both represent a moment in UTC, a specific point on the timeline. Both internally use a count since the same epoch reference of the first moment of 1970 in UTC, 1970-01-01T00:00Z. The old class uses a count of milliseconds, while Instant uses a finer count of nanoseconds.

To convert, call new methods added to the old classes.

Instant start = myJavaUtilDateStart.toInstant() ;
Instant stop = myJavaUtilDateStop.toInstant() ;

Let's make this concrete with some example values.

Instant start = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).toInstant();
Instant stop = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).plusWeeks(7 ).toInstant();

Moments versus dates

Both of our Instant objects represent a moment. The goal is a count of weeks. Weeks means days, and days mean certain dates on the calendar.

So we have a bit of a mismatch. For any given moment, the date varies around the globe by time zone. A few minutes after midnight in Paris France is a new date. Meanwhile in Montréal Québec, being several hours behind, that same moment is still “yesterday”, the date before on the calendar. So we cannot directly calculate weeks from a pair of moments.

You must first decide on the time zone by which you want to perceive a calendar for those moments.

Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ; 

ZonedDateTime

Apply this ZoneId to our Instant objects to adjust into a time zone, yielding a pair of ZonedDateTime objects.

ZonedDateTime startZdt = start.atZone( z ) ;
ZonedDateTime stopZdt = stop.atZone( z ) ;

ChronoUnit.WEEKS

Now we can use the ChronoUnit enum to calculate elapsed weeks.

long weeks = ChronoUnit.WEEKS.between( startZdt , stopZdt );

Dump to console.

System.out.println( "start.toString() = " + start );
System.out.println( "stop.toString() = " + stop );
System.out.println( "startZdt.toString() = " + startZdt );
System.out.println( "stopZdt.toString() = " + stopZdt );
System.out.println( "weeksCount: " + weeksCount );

See this code run live at IdeOne.com.

start.toString() = 2020-01-23T15:30:00Z

stop.toString() = 2020-03-12T15:30:00Z

startZdt.toString() = 2020-01-23T10:30-05:00[America/Montreal]

stopZdt.toString() = 2020-03-12T11:30-04:00[America/Montreal]

weeksCount: 7

ThreeTen-Extra

The ThreeTen-Extra project adds functionality to the java.time framework built into Java 8 and later.

Weeks class

That project includes a Weeks class to represent a number of weeks. Not only can it calculate, it is also meant to be used in your code as a type-safe object. Such use also helps to make your code self-documenting.

You can instantiate by providing a pair of points in time with the Weeks.between method. Those points in time can be anything implementing java.time.temporal.Temporal including Instant, LocalDate, OffsetDateTime, ZonedDateTime, Year, YearMonth, and more.

Your java.util.Date objects can be easily converted to Instant objects, moments on the timeline in UTC with a resolution in nanoseconds. Look at new methods added to the old date-time classes. For going from Date to Instant, call java.util.Date::toInstant.

Weeks weeks = Weeks.between( startZdt , stopZdt );

You can ask for the number of weeks.

int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.

You can also do much more.

Generate a string in standard ISO 8601 format. The P marks the beginning. The W indicates a number of weeks.

PW7


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Table of which java.time library to use with which version of Java or Android

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 13

SHIVA
SHIVA

Reputation: 706

If your requirement is like the start date is 03-Apr-2020 and end date is 07-Apr-2020. the difference between the two dates is 4 days. Now the number of weeks between two dates as 1 for this you can use below snippet.

ChronoUnit.WEEKS.between(LocalDate startDate, LocalDate endDate);

But If your requirement is like 03-Apr-2020 is in one week and 07-Apr-2020 is in another week so you want the number of weeks between two dates as 2 you can use the below snippet.

LocalDate actualStartDate=...
LocalDate actualEndDate=...

LocalDate startDate = actualStartDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY)) 

LocalDate endDate = actualEndDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SATURDAY)) 

long daysBetweenTwoDates = ChronoUnit.DAYS.between(startDate, endDate);
int numberOfWeeks =  (int)Math.ceil(daysBetweenTwoDates/7.0);

Tested in java 1.8

Upvotes: 8

Ben Noland
Ben Noland

Reputation: 34948

public int diffInWeeks(Date start, Date end) { long diffSeconds = (end.getTime() - start.getTime())/1000; return (int)diffSeconds/(60 * 60 * 24 * 7); }

Upvotes: -1

Ali Kazi
Ali Kazi

Reputation: 1636

Without using JodaTime, I was able to accurately calculate the number of weeks between 2 calendars (which accounts for leap years etc.)

private fun calculateNumberOfWeeks() {
    val calendarFrom = Calendar.getInstance()
    calendarFrom.set(Calendar.HOUR_OF_DAY, 0)
    calendarFrom.set(Calendar.MINUTE, 0)
    calendarFrom.set(Calendar.SECOND, 0)
    calendarFrom.set(Calendar.MILLISECOND, 0)

    val calendarTo = Calendar.getInstance()
    calendarTo.add(Calendar.MONTH, months)
    calendarTo.set(Calendar.HOUR_OF_DAY, 0)
    calendarTo.set(Calendar.MINUTE, 0)
    calendarTo.set(Calendar.SECOND, 0)
    calendarTo.set(Calendar.MILLISECOND, 0)

    var weeks = -1
    while (calendarFrom.timeInMillis < calendarTo.timeInMillis) {
        calendarFrom.add(Calendar.DATE, 7)
        weeks++
        Log.d(Constants.LOG_TAG, "weeks $weeks")
    }
}

Upvotes: 0

Sahil Chhabra
Sahil Chhabra

Reputation: 11716

If you want exact number of full weeks use below method, where end date is exclusive:

public static long weeksBetween(Date date1, Date date2) {
    return WEEKS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
        date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
  }

If you want a ceil version of this, use below:

public static long weeksBetween(Date date1, Date date2) {
    long daysBetween = DAYS.between(date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
        date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) + 1;
    return daysBetween / 7 + (daysBetween % 7 == 0 ? 0 : 1);
  }

Upvotes: 1

Viviano Cantu
Viviano Cantu

Reputation: 109

private int weeksBetween(Calendar startDate, Calendar endDate) {
    startDate.set(Calendar.HOUR_OF_DAY, 0);
    startDate.set(Calendar.MINUTE, 0);
    startDate.set(Calendar.SECOND, 0);
    int start = (int)TimeUnit.MILLISECONDS.toDays(
        startDate.getTimeInMillis())
        - startDate.get(Calendar.DAY_OF_WEEK);
    int end = (int)TimeUnit.MILLISECONDS.toDays(
        endDate.getTimeInMillis());
    return (end - start) / 7;
}

if this method returns 0 they are in the same week

if this method return 1 endDate is the week after startDate

if this method returns -1 endDate is the week before startDate

you get the idea

Upvotes: 0

Bene
Bene

Reputation: 1

    int startWeek = c1.get(Calendar.WEEK_OF_YEAR);
    int endWeek = c2.get(Calendar.WEEK_OF_YEAR);    

    int diff = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);

    int deltaYears = 0;
    for(int i = 0;i < diff;i++){
        deltaYears += c1.getWeeksInWeekYear();
        c1.add(Calendar.YEAR, 1);        
    }
    diff = (endWeek + deltaYears) - startWeek;

Includes the year differences. This worked for me :)

Upvotes: 0

TechTrip
TechTrip

Reputation: 4537

Updating answer to account for Java 8

// TechTrip - ASSUMPTION d1 is earlier than d2
// leave that for exercise
public static long getFullWeeks(Calendar d1, Calendar d2){

    Instant d1i = Instant.ofEpochMilli(d1.getTimeInMillis());
    Instant d2i = Instant.ofEpochMilli(d2.getTimeInMillis());

    LocalDateTime startDate = LocalDateTime.ofInstant(d1i, ZoneId.systemDefault());
    LocalDateTime endDate = LocalDateTime.ofInstant(d2i, ZoneId.systemDefault());

    return ChronoUnit.WEEKS.between(startDate, endDate);
}

Upvotes: 45

Peter Walser
Peter Walser

Reputation: 15706

Using the date arithmetic in java.util.Calendar:

public static int getWeeksBetween (Date a, Date b) {

    if (b.before(a)) {
        return -getWeeksBetween(b, a);
    }
    a = resetTime(a);
    b = resetTime(b);

    Calendar cal = new GregorianCalendar();
    cal.setTime(a);
    int weeks = 0;
    while (cal.getTime().before(b)) {
        // add another week
        cal.add(Calendar.WEEK_OF_YEAR, 1);
        weeks++;
    }
    return weeks;
}

public static Date resetTime (Date d) {
    Calendar cal = new GregorianCalendar();
    cal.setTime(d);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}

Upvotes: 8

szcoder
szcoder

Reputation: 1396

Joda Time computes weeks with durations of two dates which may not meet our requirements in some cases. I have a method with Joda Time to compute natural weeks between two dates. Hope it can help you. If you don't use Joda Time, you may modify the code with Calendar to do the same thing.

//Unlike Joda Time Weeks.weeksBetween() that returns whole weeks computed
//from duration, we return natural weeks between two dates based on week of year
public static int weeksBetween(ReadablePartial date1, ReadablePartial date2) {
    int comp = date1.compareTo(date2);
    if (comp == 0) {
        return 0;
    }

    if (comp > 0) {
        ReadablePartial mid = date2;
        date2 = date1;
        date1 = mid;
    }

    int year1 = date1.get(DateTimeFieldType.weekyear());
    int year2 = date2.get(DateTimeFieldType.weekyear());

    if (year1 == year2) {
        return date2.get(DateTimeFieldType.weekOfWeekyear()) - date1.get(DateTimeFieldType.weekOfWeekyear());
    }

    int weeks1 = 0;

    LocalDate lastDay1 = new LocalDate(date1.get(DateTimeFieldType.year()), 12, 31);
    if (lastDay1.getWeekyear() > year1) {
        lastDay1 = lastDay1.minusDays(7);
        weeks1++;
    }

    weeks1 += lastDay1.getWeekOfWeekyear() - date1.get(DateTimeFieldType.weekOfWeekyear());

    int midWeeks = 0;
    for (int i = year1 + 1; i < year2; i++) {
        LocalDate y1 = new LocalDate(i, 1, 1);
        int yearY1 = y1.getWeekyear();
        if (yearY1 < i) {
            y1 = y1.plusDays(7);
            midWeeks++;
        }

        LocalDate y2 = new LocalDate(i, 12, 31);
        int yearY2 = y2.getWeekyear();
        if (yearY2 > i) {
            y2 = y2.minusDays(7);
            midWeeks++;
        }

        midWeeks += y2.getWeekOfWeekyear() - y1.getWeekOfWeekyear();
    }

    int weeks2 = 0;
    LocalDate firstDay2 = new LocalDate(date2.get(DateTimeFieldType.year()), 1, 1);
    if (firstDay2.getWeekyear() < firstDay2.getYear()) {
        firstDay2 = firstDay2.plusDays(7);
        weeks2++;
    }
    weeks2 += date2.get(DateTimeFieldType.weekOfWeekyear()) - firstDay2.getWeekOfWeekyear();

    return weeks1 + midWeeks + weeks2;
}

Upvotes: 0

nansen
nansen

Reputation: 2962

It is pretty easy with joda time:

DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);

int weeks = Weeks.weeksBetween(dateTime1, dateTime2).getWeeks();

Upvotes: 39

Joje
Joje

Reputation: 63

You may do it the following way:

// method header not shown
// example dates:
f = new GregorianCalendar(2009,Calendar.AUGUST,1);
l = new GregorianCalendar(2010,Calendar.SEPTEMBER,1);
DateTime start = new DateTime(f);
DateTime end = new DateTime(l);
// Alternative to above - example dates with joda:
// DateTime start = new DateTime(2009,8,1,0,0,0,0);
// DateTime end = new DateTime(2010,9,1,0,0,0,0);
Interval interval = new Interval(start,end);
int weeksBetween = interval.toPeriod(PeriodType.weeks()).getWeeks();
// return weeksBetween;

This should give you an int representing the number of weeks between the two dates.

Upvotes: 0

Ishu
Ishu

Reputation: 5457

Calendar a = new GregorianCalendar(2002,1,22);
    Calendar b = new GregorianCalendar(2002,1,28);
    System.out.println(a.get(Calendar.WEEK_OF_YEAR));
    System.out.println(b.get(Calendar.WEEK_OF_YEAR)); 
   int weeks = b.get(Calendar.WEEK_OF_YEAR)-a.get(Calendar.WEEK_OF_YEAR);
    System.out.println(weeks);

try this must work

    Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.set(2007, 01, 10);
calendar2.set(2007, 07, 01);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int diffWeeks = (int)diff / (7*24 * 60 * 60 * 1000);

Upvotes: 2

Bhavin
Bhavin

Reputation: 6010

        Calendar date1 = Calendar.getInstance();
        Calendar date2 = Calendar.getInstance();

        date1.clear();
        date1.set(datePicker1.getYear(), datePicker1.getMonth(),
                datePicker1.getDayOfMonth());
        date2.clear();
        date2.set(datePicker2.getYear(), datePicker2.getMonth(),
                datePicker2.getDayOfMonth());

        long diff = date2.getTimeInMillis() - date1.getTimeInMillis();

        float dayCount = (float) diff / (24 * 60 * 60 * 1000);

        int week = (dayCount / 7) ;

Hope this might Help you

Upvotes: -1

MikeAr
MikeAr

Reputation: 1051

Take a look at the following article: Java - calculate the difference between two dates

The daysBetween method will allow you to get the number of days between dates. Then you can simply divide by 7 to get the number of full weeks.

Upvotes: -1

Related Questions