How do I find the nth previous Sunday with Java or Joda-time dates API?

How do we calculate the previous Sunday or the previous Sunday, or generally tell how to find out Sunday before n weeks? The catch, if today is Sunday, it should be back today Sunday, not last week.

Looking for a Joda-Time or Java 8 solution.

Edit: I tried

DateTime sunday = now
    .minusWeeks(1)
    .withDayOfWeek(DateTimeConstants.SUNDAY)
    .wi‌​thTimeAtStartOfDay()‌​;
DateTime previousWeekSunday = now
    .minusWeeks(2)
    .withDayOfWeek(DateTimeConstants.SATURDAY)
    .‌​withTime(23, 59, 59, 999); 

      

but if the current is Sunday, then this logic fails as it does not give today the date.

+3


source to share


2 answers


You need to check if today is Sunday, and if not, then look back to the previous one ... (or recursively return the date if you need the previous one to ...)

Using java 8 you will need:




LocalDate date = LocalDate.now();
DayOfWeek todayAsDayOfWeek = date.getDayOfWeek();
LocalDate prevSun = todayAsDayOfWeek == DayOfWeek.SUNDAY ? date : date.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY));
System.out.println(prevSun);

      




Edit: the previousOrSame method will skip checking the actual day of the week

    LocalDate date = LocalDate.now();
    LocalDate prevSun = date.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY));

    prevSun = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));
    System.out.println(prevSun);

      

+4


source


The question was already covered with a Java 8 approach, but for the record, there was a Joda-Time solution here (as well as my 2 cents for Java 8).

If I understood correctly, the general algorithm for getting the n th of the previous Sunday is:

  • If today's date is already Sunday, return n-1

    weeks (so n=1

    it returns the same date for)
  • else, find n th the previous sunday from that date

I created a method that gets n

(number of weeks) and DateTime

(start date). Code:

// get the n'th previous Sunday, from the given DateTime
public DateTime nPreviousSunday(int n, DateTime dateTime) {
    // avoid zero or negative numbers (optional, see if it fits your use cases)
    if (n <= 0) {
        return dateTime; // return the same date
    }

    DateTime d = dateTime;

    // get first previous (or same) Sunday
    int dow = d.getDayOfWeek();
    if (dow != DateTimeConstants.SUNDAY) { // not a Sunday, adjust the day to the previous one
        int diff = DateTimeConstants.SUNDAY - dow;
        // DateTimeConstants.SUNDAY is 7, so diff is always positive
        // d is (7 - diff) days ahead of Sunday, adjusting
        d = d.minusDays(7 - diff);
    }

    // find the n'th previous (considering that the first was already found above)
    d = d.minusWeeks(n - 1);

    return d;
}

      

Below are the tests for 04/06/2017

(Sunday). For, n=1

it returns 04/06/2017

, and for n >= 2

finds n th the previous Sunday from that date (assuming itself 04/06/2017

is the first):

System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 4, 10, 0))); // 2017-06-04
System.out.println(nPreviousSunday(2, new DateTime(2017, 6, 4, 10, 0))); // 2017-05-28
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 4, 10, 0))); // 2017-05-21

      

Testing for 05/06/2017

(not Sunday), it gets the same results (as the previous Sunday 04/06/2017

):

System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 5, 10, 0))); // 2017-06-04
System.out.println(nPreviousSunday(2, new DateTime(2017, 6, 5, 10, 0))); // 2017-05-28
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 5, 10, 0))); // 2017-05-21

      

Testing for the whole week until Saturday ( 10/06/2017

):

System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 6, 10, 0))); // 2017-06-04
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 7, 10, 0))); // 2017-06-04
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 8, 10, 0))); // 2017-06-04
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 9, 10, 0))); // 2017-06-04
System.out.println(nPreviousSunday(1, new DateTime(2017, 6, 10, 10, 0))); // 2017-06-04

System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 6, 10, 0))); // 2017-05-21
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 7, 10, 0))); // 2017-05-21
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 8, 10, 0))); // 2017-05-21
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 9, 10, 0))); // 2017-05-21
System.out.println(nPreviousSunday(3, new DateTime(2017, 6, 10, 10, 0))); // 2017-05-21

      

PS : I use DateTime

, but you can also use this code for org.joda.time.LocalDate

or org.joda.time.LocalDateTime

(the algorithm is the same, just change the type of the variable in the method).


Java 8 approach (my 2 cents)

In Java 8 you can use TemporalAdjuster

as already answered . But just to fit 2 cents, you can create a method that returns TemporalAdjuster

and then you can use it with any of the java time types:



// get the n'th previous dayOfWeek, from the given temporal
public TemporalAdjuster previous(int n, DayOfWeek dayOfWeek) {
    return (temporal) -> {
        // avoid zero or negative numbers (optional, see if it fits your use cases)
        if (n <= 0) {
            return temporal; // return the same temporal
        }

        // get first previous (or same) dayOfWeek
        Temporal t = temporal.with(TemporalAdjusters.previousOrSame(dayOfWeek));

        // find the n'th previous (considering that the first was already found above)
        t = t.minus(n - 1, ChronoUnit.WEEKS);

        return t;
    };
}

      

So, you can use it like this:

System.out.println(LocalDate.of(2017, 6, 4).with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04
System.out.println(LocalDate.of(2017, 6, 4).with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28
System.out.println(LocalDate.of(2017, 6, 4).with(previous(3, DayOfWeek.SUNDAY))); // 2017-05-21

System.out.println(LocalDate.of(2017, 6, 5).with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04
System.out.println(LocalDate.of(2017, 6, 5).with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28
System.out.println(LocalDate.of(2017, 6, 5).with(previous(3, DayOfWeek.SUNDAY))); // 2017-05-21

      

The good thing is that it works with other types as well:

LocalDateTime dt = LocalDateTime.of(2017, 6, 4, 10, 0);
System.out.println(dt.with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04T10:00
System.out.println(dt.with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28T10:00

ZonedDateTime zdt = ZonedDateTime.of(dt, ZoneId.of("America/Sao_Paulo"));
System.out.println(zdt.with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04T10:00-03:00[America/Sao_Paulo]
System.out.println(zdt.with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28T10:00-03:00[America/Sao_Paulo]

OffsetDateTime odt = OffsetDateTime.of(dt, ZoneOffset.ofHours(2));
System.out.println(odt.with(previous(1, DayOfWeek.SUNDAY))); // 2017-06-04T10:00+02:00
System.out.println(odt.with(previous(2, DayOfWeek.SUNDAY))); // 2017-05-28T10:00+02:00

      

When the method previous()

returns TemporalAdjuster

, you don't need to call it every time, just store the regulator in a variable and reuse it:

TemporalAdjuster thirdPreviousSunday = previous(3, DayOfWeek.SUNDAY);
System.out.println(LocalDate.of(2017, 6, 4).with(thirdPreviousSunday)); // 2017-05-21
System.out.println(LocalDate.of(2017, 6, 5).with(thirdPreviousSunday)); // 2017-05-21

      

Other benefits of this approach are: the code is clearer and cleaner (IMO) and it works any day of the week.


PS: The code below throws an exception if the type has no field DayOfWeek

(for example LocalTime

, which only has an hour / minute / second / nanosecond):

// throws UnsupportedTemporalTypeException (because LocalTime doesn't have the DayOfWeek field)
LocalTime.now().with(previous(1, DayOfWeek.SUNDAY));

      

We remind you that this is already happening with existing regulators:

// also throws exception (Unsupported field: DayOfWeek)
LocalTime.now().with(TemporalAdjusters.previous(DayOfWeek.SUNDAY));

      

This makes sense as LocalTime

it has no date fields and cannot know about weekdays.

+1


source







All Articles