How to find nearest week day for an arbitrary date?

删除回忆录丶 提交于 2019-12-08 19:01:35

问题


Is there an elegant way to find the nearest day of the week for a given date using JodaTime? I initially thought setCopy() would be it, but this sets the day to the particular day in the same week. Thus, if ld is 2011-11-27 and day is "Monday" the following function returns 2011-11-21, and not 2011-11-28 as I want.

    // Note that "day" can be _any_ day of the week, not just weekdays.
    LocalDate getNearestDayOfWeek(LocalDate ld, String day) {
        return ld.dayOfWeek().setCopy(day);
    }

Desired output for various inputs:

2011-12-04, Monday    => 2011-12-05
2011-12-04, Tuesday   => 2011-12-06
2011-12-04, Wednesday => 2011-12-07
2011-12-04, Thursday  => 2011-12-01
2011-12-04, Friday    => 2011-12-02
2011-12-04, Saturday  => 2011-12-03
2011-12-04, Sunday    => 2011-12-04

2011-12-05, Monday    => 2011-12-05
2011-12-05, Tuesday   => 2011-12-06
2011-12-05, Wednesday => 2011-12-07
2011-12-05, Thursday  => 2011-12-08
2011-12-05, Friday    => 2011-12-02
2011-12-05, Saturday  => 2011-12-03
2011-12-05, Sunday    => 2011-12-04

Below is a work-around I came up with that works for the particular constraints in my current situation, but I'd love to get help find a completely generic solution that works always.

    LocalDate getNearestDayOfWeek(LocalDate ld, String day) {
        LocalDate target = ld.dayOfWeek().setCopy(day);
        if (ld.getDayOfWeek() > DateTimeConstants.SATURDAY) {
            target = target.plusWeeks(1);
        }
        return target;
    }

回答1:


In Jodatime, this kind of thing should be doable with three or four lines:

   /** Given a reference LocalDate and a day of week, eg DateTimeConstants.MONDAY 
       Returns the nearest date with that day of week */
   public static LocalDate getNearestDayOfWeek(LocalDate t0,int dow) {
        LocalDate t1 = t0.withDayOfWeek(dow);
        LocalDate t2 = t1.isBefore(t0) ? t1.plusWeeks(1) : t1.minusWeeks(1);
        return  Math.abs(Days.daysBetween(t1, t0).getDays()) < 
                Math.abs(Days.daysBetween(t2, t0).getDays()) ? t1 : t2;
   }

Or more compact and efficient:

public static LocalDate getNearestDayOfWeek(LocalDate t0, int dow) {
    LocalDate t1 = t0.withDayOfWeek(dow);
    if (t1.isBefore(t0.minusDays(3)))       return t1.plusWeeks(1);
    else if (t1.isAfter(t0.plusDays(3)))    return t1.minusWeeks(1);
    else return t1;
}

And if you want to pass the day-of-the-week as String:

public static LocalDate getNearestDayOfWeek(LocalDate t0, String dow) {
    return getNearestDayOfWeek(t0,t0.dayOfWeek().setCopy(dow).getDayOfWeek());
}

Example:

    // prints 2011-11-28
   public static  void  main(String[] args) throws Exception {
        LocalDate today = new LocalDate(2011,11,27);
        int dow = DateTimeConstants.MONDAY;
        System.out.println(getNearestDayOfWeek(today ,dow ));
   }



回答2:


Here is an approach to the problem. I know a little bit about JodaTime, but not all the classes and methods. I'm assuming that given a date, you can get the day of the week and the next or previous dates.

There are three cases.

  1. The dayOfTheWeek for a particular date is a weekday. Return date.
  2. The dayOfTheWeekis Saturday. Subtract 1 day from your date. Return the date - 1 day.
  3. The dayOfTheWeekis Sunday. Add 1 day to your date. Return the date + one day.

If dayOfTheWeek is an enumerated type, then a case statement would handle the task in a straight forward manner.




回答3:


This finds the nearest day of the week by defining an interval of closest days of the week. Joda defines a week as starting on Monday. So if today is Tuesday and the day of the week is set to Sunday, the date will be for the following Sunday, not the previous. If the first day of the week is redefined to be Sunday, the date returned will be for the previous Sunday. The following code isn't effected by the definition of the first day of the week.

DateTime getNearestDayOfWeek(DateTime dateTime, String day) {
  //Create an interval containing the nearest days of the week.
  DateTime begin = dateTime.minusHours(DateTimeConstants.HOURS_PER_WEEK/2).dayOfWeek().roundHalfCeilingCopy();
  DateTime end   = dateTime.plusHours(DateTimeConstants.HOURS_PER_WEEK/2).dayOfWeek().roundHalfCeilingCopy();
  Interval interval = new Interval(begin, end);

  //Adjust nearest day to be within the interval. Doesn't depend on definition of first day of the week.
  DateTime nearest  = dateTime.dayOfWeek().setCopy(day);
  if (interval.isAfter(nearest))  //nearest is before the interval
    return nearest.plusWeeks(1);
  else if (interval.isBefore(nearest))  //nearest is after the interval
    return nearest.minusWeeks(1);
  else 
    return nearest;
}



回答4:


Something like this. For the dayOfWeek parameter, use the constants defined in org.joda.time.DateTimeConstants:

public LocalDate getNext(int dayOfWeek) {
    LocalDate today = new LocalDate();
    return getNext(dateOfWeek, today);
}

public LocalDate getNext(int dayOfWeek, LocalDate fromDate) {
    int dayOffset = DateTimeConstants.DAYS_PER_WEEK - dayOfWeek + 1;
    LocalDate weekContainingDay = fromDate.plusDays(dayOffset);

    return weekContainingDay.withDayOfWeek(dayOfWeek);
}

Usage:

LocalDate nextSunday = foo.getNext(DateTimeConstants.SUNDAY);



回答5:


Based on Richard Povinelli's answer, but updated to use Java Time (as of Java 8)

public static LocalDate getNearestDayOfWeek(LocalDate date, DayOfWeek dayOfWeek) {
    LocalDate start = date.minusDays(3);
    LocalDate end = date.plusDays(3);
    LocalDate guessDate = date.with(dayOfWeek);
    // the nearest day is between start and end, so we adjust our guess if required
    if (guessDate.isAfter(end)) {
        // guessed one week to late
        return guessDate.minusWeeks(1);
    } else if (guessDate.isBefore(start)) {
        // guessed one week to early
        return guessDate.plusWeeks(1);
    } else {
        // the guess was correct
        return guessDate;
    }
}


来源:https://stackoverflow.com/questions/8321537/how-to-find-nearest-week-day-for-an-arbitrary-date

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!