Time: How to get the next friday?
Asked Answered
O

9

78

How can I get the next friday with the Joda-Time API.

The LocalDate of today is today. It looks to me you have to decide whever you are before or after the friday of the current week. See this method:

private LocalDate calcNextFriday(LocalDate d) {
    LocalDate friday = d.dayOfWeek().setCopy(5);
    if (d.isBefore(friday)) {
        return d.dayOfWeek().setCopy(5);
    } else {
        return d.plusWeeks(1).dayOfWeek().setCopy(5);
    }
}

Is it possible to do it shorter or with a oneliner?

PS: Please don't advise me using JDKs date/time stuff. Joda-Time is a much better API.

Java 8 introduces java.time package (Tutorial) which is even better.

Opaque answered 28/10, 2009 at 9:16 Comment(5)
good question... DateTime could use a rollForwardTo(...) methodTrapani
@Trapani See my generic rollForward answer. Its not super duper tested but seems to work for me.Biforked
Actually, java.time is not necessarily better that Joda-Time. Each has features the other lacks. For example, java.time lacks the Interval class found in Joda-Time. So use each for its strengths. You can mix and match within a project. Just be careful with your import statements as a few of their classes share the same name.Callimachus
The equivalent question, but for Java time instead of Joda-Time: https://mcmap.net/q/266121/-find-next-occurrence-of-a-day-of-week-in-jsr-310/1108305Culberson
To update my Comment above: I have changed my advice. You should migrate away from Joda-Time as soon as is convenient. That project is in maintenance mode, with no further feature work to be done. To regain some of the features present in Joda-Time but missing in java.time, add the ThreeTen-Extra library to your project. For example, that library offers classes for Interval and LocalDateRange.Callimachus
O
126

java.time

With the java.time framework built into Java 8 and later (Tutorial) you can use TemporalAdjusters to get next or previous day-of-week.

private LocalDate calcNextFriday(LocalDate d) {
  return d.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
}
Opaque answered 12/3, 2015 at 12:53 Comment(4)
Does this uses joda-time?Northward
No, but it developed from it. Here a quote from the joda time homepage: Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (JSR-310).Opaque
FYI, the java.time classes are built into Java 8 and later. Much of the java.time functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP. Also, see Oracle Tutorial to learn more.Callimachus
Equivalent question, but for Java time instead of Joda Time: https://mcmap.net/q/266121/-find-next-occurrence-of-a-day-of-week-in-jsr-310/1108305Culberson
G
52

It's possible to do it in a much easier to read way:

if (d.getDayOfWeek() < DateTimeConstants.FRIDAY) {
    return d.withDayOfWeek(DateTimeConstants.FRIDAY));
} else if (d.getDayOfWeek() == DateTimeConstants.FRIDAY) {
    // almost useless branch, could be merged with the one above
    return d;
} else {
    return d.plusWeeks(1).withDayOfWeek(DateTimeConstants.FRIDAY));
}

or in a bit shorter form

private LocalDate calcNextFriday(LocalDate d) {    
    if (d.getDayOfWeek() < DateTimeConstants.FRIDAY) {
        d = d.withDayOfWeek(DateTimeConstants.FRIDAY));
    } else {
        d = d.plusWeeks(1).withDayOfWeek(DateTimeConstants.FRIDAY));
    }    
    return d; // note that there's a possibility original object is returned
}

or even shorter

private LocalDate calcNextFriday(LocalDate d) {
    if (d.getDayOfWeek() >= DateTimeConstants.FRIDAY) {
        d = d.plusWeeks(1);
    }
    return d.withDayOfWeek(DateTimeConstants.FRIDAY);
}

PS. I didn't test the actual code! :)

Georgetta answered 28/10, 2009 at 9:56 Comment(2)
or compile it ... "DateTimeConstans"Class
Your last snippet's "return" line contains a redundant ")" character. Anyways, thanks, great solution!Unicorn
B
5

Your code in 1 line

private LocalDate calcNextFriday3(LocalDate d) {
    return d.isBefore(d.dayOfWeek().setCopy(5))?d.dayOfWeek().setCopy(5):d.plusWeeks(1).dayOfWeek().setCopy(5);
}

Alternative approach

private LocalDate calcNextDay(LocalDate d, int weekday) {
    return (d.getDayOfWeek() < weekday)?d.withDayOfWeek(weekday):d.plusWeeks(1).withDayOfWeek(weekday);
}


private LocalDate calcNextFriday2(LocalDate d) {
    return calcNextDay(d,DateTimeConstants.FRIDAY);
}

somewhat tested ;-)

Bannockburn answered 28/10, 2009 at 10:6 Comment(3)
Thanks for your answer. Your suggestion with the more general approach is nice. But the oneliner is awkward in term of readability.Opaque
@michaelkebe you asked for a oneliner, I just provided one... ;-)Bannockburn
@Opaque I usually place newlines with ternaries at "?" and ":", hit format in Eclipse and it arranges pretty well.Unicorn
B
4

I just wasted like 30 minutes trying to figure this out myself but I needed to generically roll forward.

Anyway here is my solution:

public static DateTime rollForwardWith(ReadableInstant now, AbstractPartial lp) {
    DateTime dt = lp.toDateTime(now);
    while (dt.isBefore(now)) {
        dt = dt.withFieldAdded(lp.getFieldTypes()[0].getRangeDurationType(), 1);
    }
    return dt;
}

Now you just need to make a Partial (which LocalDate is) for the day of the week.

Partial().with(DateTimeFieldType.dayOfWeek(), DateTimeConstants.FRIDAY); 

Now whatever the most significant field is of the partial will be +1 if the current date is after it (now).

That is if you make a partial with March 2012 it will create a new datetime of March 2013 or <.

Biforked answered 18/7, 2012 at 3:1 Comment(0)
N
4
import java.util.Calendar;

private Calendar getNextweekOfDay(int weekOfDay) {
    Calendar today = Calendar.getInstance();
    int dayOfWeek = today.get(Calendar.DAY_OF_WEEK);
    int daysUntilNextWeekOfDay = weekOfDay - dayOfWeek;
    if (daysUntilNextWeekOfDay == 0) daysUntilNextWeekOfDay = 7;
    Calendar nextWeekOfDay = (Calendar)today.clone();
    nextWeekOfDay.add(Calendar.DAY_OF_WEEK, daysUntilNextWeekOfDay);
    return nextWeekOfDay;
}

// set alarm for next Friday 9am
public void setAlarm() {
    Calendar calAlarm = getNextweekOfDay(Calendar.FRIDAY);
    calAlarm.set(Calendar.HOUR_OF_DAY, 9);//9am
    calAlarm.set(Calendar.MINUTE, 0);
    calAlarm.set(Calendar.SECOND, 0);
    scheduleAlarm(calAlarm);// this is my own method to schedule a pendingIntent
}
Northnortheast answered 16/6, 2015 at 7:19 Comment(1)
FYI, the terribly troublesome old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle.Callimachus
T
3

counting bytes @fvu answer can be shortened even further to:

private LocalDate calcNextFriday(LocalDate d) {
  return d.plusWeeks(d.getDayOfWeek() < DateTimeConstants.FRIDAY ? 0 : 1).withDayOfWeek(DateTimeConstants.FRIDAY);
}
Typist answered 6/10, 2014 at 10:18 Comment(0)
S
0

A simple modulo based solution which should work with most of former java versions in case you are not allowed to upgrade your java version to java8 or onwards or to use a standard java date library as jodatime

Number of days to add to your date is given by this formula :

(7 + Calendar.FRIDAY - yourDateAsCalendar.get(Calendar.DAY_OF_WEEK)) % 7

Note also this can be generalized for any week day by changing the static field Calendar.FRIDAY to your given weekday. Some snippet code below

public static void main(String[] args) {
    for (int i = 0; i < 15; i++) {

        Calendar cur = Calendar.getInstance();
        cur.add(Calendar.DAY_OF_MONTH, i);

        Calendar friday = Calendar.getInstance();
        friday.setTime(cur.getTime());
        friday.add(Calendar.DAY_OF_MONTH, (7 + Calendar.FRIDAY - cur.get(Calendar.DAY_OF_WEEK)) % 7);

        System.out.println(MessageFormat.format("Date {0} -> {1} ", cur.getTime(),  friday.getTime()));
    }
}
Sommer answered 22/11, 2018 at 1:39 Comment(2)
FYI, the terribly troublesome old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle.Callimachus
Yes If you use java 8 or onwards version or Jodatime, this is not for you. I did say it but i was not clear. Thanks for commenting.Sommer
J
0

Here's an alternative way of doing it, without using any other classes/APIs outside LocalDate.

     LocalDate nextFriday = (d.plusWeeks(1).withDayOfWeek(5).minusDays(7).isAfter(d)) 
                            ? d.plusWeeks(1).withDayOfWeek(5)
                            : d.withDayOfWeek(5);
Junkojunkyard answered 8/3, 2021 at 11:57 Comment(2)
How is it better than the accepted answer? I guess it’s correct, but I have a very hard time convincing myself.Bullfighter
no-one saying it's better, just an alternative way of doing the same. I believe my answer has clear logic and it doesn't require knowledge/usage of different APIs/ classes other than LocalDateJunkojunkyard
T
0

Using Joda-Time 2.12.2, below is a pure function which will find the next/prior Day of the Week as a LocalDate using ISO8601 constants.

Parameters:

  • localDate: the anchor date
  • isoDayOfWeek: the specific Day of the Week desired
    • the weekday number, from 1 through 7
    • beginning with Monday and ending with Sunday
  • howManyWeeksOut: how far forward/backward to offset in weeks, with 0 meaning closest
  • isPast: when true, offset backwards in time, otherwise offset forwards
  • isExcludingToday: when true and isoDayOfWeek is equal to localDate.getDayOfWeek(), offset forward/backwards a full week from localDate
import org.joda.time.LocalDate;

public static LocalDate toDayOfWeek(
    LocalDate localDate,
    int isoDayOfWeek,
    int howManyWeeksOut,
    boolean isPast,
    boolean isExcludingToday
) {
  var localDateDayOfWeek = localDate.getDayOfWeek();
  if ((localDateDayOfWeek == isoDayOfWeek) && !isExcludingToday && (howManyWeeksOut == 0)) {
    return localDate;
  }
  var daysUntilIsoDayOfWeek =
      isoDayOfWeek + ((isoDayOfWeek < localDateDayOfWeek) ? 7 : 0) - localDateDayOfWeek;
  var weeksOffset =
      7 * (howManyWeeksOut + ((daysUntilIsoDayOfWeek == 0) && isExcludingToday ? 1 : 0));

  return (!isPast)
      ? localDate.plusDays(daysUntilIsoDayOfWeek + weeksOffset)
      : localDate.minusDays(((daysUntilIsoDayOfWeek != 0) ? (7 - daysUntilIsoDayOfWeek) : 0) + weeksOffset);
}
Trager answered 20/2, 2023 at 15:11 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.