Java Joda Time Minus Weeks()和plusweeks()的2014/2015年年假细分?

Java Joda Time Minus Weeks()和plusweeks()的2014/2015年年假细分?,java,jodatime,Java,Jodatime,我可能在这里遗漏了一些东西,但我似乎无法在Joda Time的文档或任何地方找到解释。当你从一年到下一年计算周数时,加减周数时,Joda Time似乎会崩溃 有人能解释为什么会发生这种情况以及如何正确地做到这一点吗 我从下面的代码中获得以下输出: 2015-01-08 - This is the current week 2015-01-01 - Removed one week 2014-12-25 - Removed one week 2014-12-17 - Removed one wee

我可能在这里遗漏了一些东西,但我似乎无法在Joda Time的文档或任何地方找到解释。当你从一年到下一年计算周数时,加减周数时,Joda Time似乎会崩溃

有人能解释为什么会发生这种情况以及如何正确地做到这一点吗

我从下面的代码中获得以下输出:

2015-01-08 - This is the current week
2015-01-01 - Removed one week
2014-12-25 - Removed one week
2014-12-17 - Removed one week //for some reason, program backed 8 days here
2014-12-10 - Removed one week
2014-12-17 - Added one week
2014-12-24 - Added one week
2014-12-31 - Added one week
2014-01-08 - Added one week //for some reason, program forwarded 8 days here, but it did not forward to 2015.
原始代码

import org.joda.time.*;

public class WonkyWeeks {
    int year;
    int week;

    public void backUpOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate lastWeek = today.minusWeeks(1);

        week = lastWeek.getWeekOfWeekyear();
        year = lastWeek.getYear();
        System.out.println(lastWeek+" - Removed one week");
    }

    public void forwardOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate nextWeek = today.plusWeeks(1);

        week = nextWeek.getWeekOfWeekyear();
        year = nextWeek.getYear();
        System.out.println(nextWeek+" - Added one week");
    }

    public void thisWeek() {
        LocalDate thisWeek = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        System.out.println(thisWeek+" - This is the current week");
    }

    public static void main(String[] args) {
        WonkyWeeks wonky = new WonkyWeeks();
        wonky.week = 2;
        wonky.year = 2015;
        wonky.thisWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
    }
}
import org.joda.time.*;

public class WonkyWeeks {
    int year;
    int week;

    public void backUpOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate adayago = today.minusDays(1);
        System.out.println(adayago+" - removed one day");
        LocalDate twodaysago = adayago.minusDays(1);
        System.out.println(twodaysago+" - removed one day");
        LocalDate threedaysago = twodaysago.minusDays(1);
        System.out.println(threedaysago+" - removed one day");
        LocalDate fourdaysago = threedaysago.minusDays(1);
        System.out.println(fourdaysago+" - removed one day");
        LocalDate fivedaysago = fourdaysago.minusDays(1);
        System.out.println(fivedaysago+" - removed one day");
        LocalDate sixdaysago = fivedaysago.minusDays(1);
        System.out.println(sixdaysago+" - removed one day");
        LocalDate lastWeek = sixdaysago.minusDays(1);

        week = lastWeek.getWeekOfWeekyear();
        year = lastWeek.getYear();
        System.out.println(lastWeek+" - Removed one full week");
    }
    public void forwardOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate tomorrow = today.plusDays(1);
        System.out.println(tomorrow+" - added one day");
        LocalDate dayAfterTomorrow = tomorrow.plusDays(1);
        System.out.println(dayAfterTomorrow+" - added one day");
        LocalDate threeDaysFromNow = dayAfterTomorrow.plusDays(1);
        System.out.println(threeDaysFromNow+" - added one day");
        LocalDate fourDaysFromNow = threeDaysFromNow.plusDays(1);
        System.out.println(fourDaysFromNow+" - added one day");
        LocalDate fiveDaysFromNow = fourDaysFromNow.plusDays(1);
        System.out.println(fiveDaysFromNow+" - added one day");
        LocalDate sixDaysFromNow = fiveDaysFromNow.plusDays(1);
        System.out.println(sixDaysFromNow+" - added one day");
        LocalDate nextWeek = sixDaysFromNow.plusDays(1);

        week = nextWeek.getWeekOfWeekyear();
        year = nextWeek.getYear();
        System.out.println(nextWeek+" - Added one week");
    }
    public void thisWeek() {
        LocalDate thisWeek = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        System.out.println(thisWeek+" - This is the current week");
    }
    public static void main(String[] args) {
        WonkyWeeks wonky = new WonkyWeeks();
        wonky.week = 2;
        wonky.year = 2015;
        wonky.thisWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
    }
}
经过进一步的测试,它变得更加混乱。我试着只添加和删除几天而不是几周,出于某种原因,它似乎跳过了日期

输出:

2015-01-08 - This is the current week
2015-01-07 - removed one day
2015-01-06 - removed one day
2015-01-05 - removed one day
2015-01-04 - removed one day
2015-01-03 - removed one day
2015-01-02 - removed one day
2015-01-01 - Removed one full week
2014-12-31 - removed one day
2014-12-30 - removed one day
2014-12-29 - removed one day
2014-12-28 - removed one day
2014-12-27 - removed one day
2014-12-26 - removed one day
2014-12-25 - Removed one full week
2014-12-23 - removed one day // For some reason, it skipped 2014-12-24?
2014-12-22 - removed one day
2014-12-21 - removed one day
2014-12-20 - removed one day
2014-12-19 - removed one day
2014-12-18 - removed one day
2014-12-17 - Removed one full week
2014-12-16 - removed one day
2014-12-15 - removed one day
2014-12-14 - removed one day
2014-12-13 - removed one day
2014-12-12 - removed one day
2014-12-11 - removed one day
2014-12-10 - Removed one full week
2014-12-11 - added one day
2014-12-12 - added one day
2014-12-13 - added one day
2014-12-14 - added one day
2014-12-15 - added one day
2014-12-16 - added one day
2014-12-17 - Added one week
2014-12-18 - added one day
2014-12-19 - added one day
2014-12-20 - added one day
2014-12-21 - added one day
2014-12-22 - added one day
2014-12-23 - added one day
2014-12-24 - Added one week
2014-12-25 - added one day
2014-12-26 - added one day
2014-12-27 - added one day
2014-12-28 - added one day
2014-12-29 - added one day
2014-12-30 - added one day
2014-12-31 - Added one week
2014-01-02 - added one day //Skipped 2014-01-01 and did not forward to 2015
2014-01-03 - added one day
2014-01-04 - added one day
2014-01-05 - added one day
2014-01-06 - added one day
2014-01-07 - added one day
2014-01-08 - Added one week
进一步测试代码

import org.joda.time.*;

public class WonkyWeeks {
    int year;
    int week;

    public void backUpOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate lastWeek = today.minusWeeks(1);

        week = lastWeek.getWeekOfWeekyear();
        year = lastWeek.getYear();
        System.out.println(lastWeek+" - Removed one week");
    }

    public void forwardOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate nextWeek = today.plusWeeks(1);

        week = nextWeek.getWeekOfWeekyear();
        year = nextWeek.getYear();
        System.out.println(nextWeek+" - Added one week");
    }

    public void thisWeek() {
        LocalDate thisWeek = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        System.out.println(thisWeek+" - This is the current week");
    }

    public static void main(String[] args) {
        WonkyWeeks wonky = new WonkyWeeks();
        wonky.week = 2;
        wonky.year = 2015;
        wonky.thisWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
    }
}
import org.joda.time.*;

public class WonkyWeeks {
    int year;
    int week;

    public void backUpOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate adayago = today.minusDays(1);
        System.out.println(adayago+" - removed one day");
        LocalDate twodaysago = adayago.minusDays(1);
        System.out.println(twodaysago+" - removed one day");
        LocalDate threedaysago = twodaysago.minusDays(1);
        System.out.println(threedaysago+" - removed one day");
        LocalDate fourdaysago = threedaysago.minusDays(1);
        System.out.println(fourdaysago+" - removed one day");
        LocalDate fivedaysago = fourdaysago.minusDays(1);
        System.out.println(fivedaysago+" - removed one day");
        LocalDate sixdaysago = fivedaysago.minusDays(1);
        System.out.println(sixdaysago+" - removed one day");
        LocalDate lastWeek = sixdaysago.minusDays(1);

        week = lastWeek.getWeekOfWeekyear();
        year = lastWeek.getYear();
        System.out.println(lastWeek+" - Removed one full week");
    }
    public void forwardOneWeek() {
        LocalDate today = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        LocalDate tomorrow = today.plusDays(1);
        System.out.println(tomorrow+" - added one day");
        LocalDate dayAfterTomorrow = tomorrow.plusDays(1);
        System.out.println(dayAfterTomorrow+" - added one day");
        LocalDate threeDaysFromNow = dayAfterTomorrow.plusDays(1);
        System.out.println(threeDaysFromNow+" - added one day");
        LocalDate fourDaysFromNow = threeDaysFromNow.plusDays(1);
        System.out.println(fourDaysFromNow+" - added one day");
        LocalDate fiveDaysFromNow = fourDaysFromNow.plusDays(1);
        System.out.println(fiveDaysFromNow+" - added one day");
        LocalDate sixDaysFromNow = fiveDaysFromNow.plusDays(1);
        System.out.println(sixDaysFromNow+" - added one day");
        LocalDate nextWeek = sixDaysFromNow.plusDays(1);

        week = nextWeek.getWeekOfWeekyear();
        year = nextWeek.getYear();
        System.out.println(nextWeek+" - Added one week");
    }
    public void thisWeek() {
        LocalDate thisWeek = new LocalDate()
                .withDayOfWeek(4)
                .withWeekOfWeekyear(week)
                .withYear(year);
        System.out.println(thisWeek+" - This is the current week");
    }
    public static void main(String[] args) {
        WonkyWeeks wonky = new WonkyWeeks();
        wonky.week = 2;
        wonky.year = 2015;
        wonky.thisWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
    }
}

我看你的逻辑没有问题。在尝试了不同的场景并调试了一些代码之后,我相信这是由于不同年份的
dayOfWeek
的行为造成的

这可能无法为您的问题提供完整的答案,但可能会给您一个提示

无论是哪一年,您都会通过一周中的第四天。但它代表不同的日子,取决于年份。 例如,如果您将第1周和2013年的
天设为4,然后调用
getDayOfWeek()
,您将得到值为
2
(星期二)

同样,2014年的
getDayOfWeek()
将返回
3
(星期三),2015年的
4
(星期四)

因此,对于2015年,第4周的一天代表周四,而对于2014年,它代表周三

现在让我们看看您的用例:

  • 2015-01-08-这是本周(第2周,第4天-周四)
  • 2015-01-01-删除一周-(第1周,第4天-周四)
  • 2014年12月25日-删除一周-(第4周,第4天-周四)
  • 2014年12月17日-删除一周-(此处更正-第3周,第2天) 第四-周三)

我不确定为什么没有在
2014-12-25

上进行更正。Joda时间是正确的,但不是您的逻辑。您必须仔细区分“日历年”(从1月1日开始)和周日期的年份(定义见ISO-8601,也称为“基于周的年”或简称“周年”)

例如,您在类中使用两个彼此不严格相关的成员来存储中间结果:

week = nextWeek.getWeekOfWeekyear();
year = nextWeek.getYear();
这些行的问题在于周与基于周的年份相关,而不是与第二行所示的日历年相关。请记住,基于周的年份可以比1月1日的日历年少一年。例如[2014-12-31]与[2015-W01-3]的日期相同。还要记住,Joda Time提供了另一种方法,称为
getWeekyear()

然后,您将使用这两个值以这种方式操纵日期:

LocalDate today = new LocalDate()
        .withDayOfWeek(4)
        .withWeekOfWeekyear(week)
        .withYear(year);
同样的术语问题。当试图在当前周年2015年内保留周日时,
withWeekOfWeekyear(week)
方法已经可以更改日历年并将月日移到另一天,而不是2014日历年产生意外的日期移动!整个代码产生的结果不是真正可预测的,会让每个人都感到惊讶。另一个大问题是方法调用的顺序,这很重要,因为周操作指的是当前的周年(哪一个?!)。以下代码看起来更健康:

LocalDate today = new LocalDate()
        .withWeekyear(year)
        .withWeekOfWeekyear(week)
        .withDayOfWeek(4);
解决方案:您最好在代码中引用周年,而不是日历年。或者更好:如果您只是想添加或删除周,那么我建议您存储日期(作为类型为
LocalDate
的对象),并应用
date.plusWeeks(1)
或类似的方法。您始终可以查询星期日、基于年的星期、星期年、日历年等的日期,这比保存年的星期和日历年要好得多

测试后更新:

现在,我已经将年更改为周年,并且在设置日期时也更改了方法调用的顺序(首先是周年,然后是周,最后是星期几)。在这些更改之后,根据我自己的测试,您的代码将可以正常工作(尽管我仍然建议您简化类状态和逻辑)。这里是我的完整更改和更正代码:

import org.joda.time.LocalDate;

public class WonkyWeeks {
    int year;
    int week;

    public void backUpOneWeek() {
        LocalDate today =
            new LocalDate().withWeekyear(year).withWeekOfWeekyear(week).withDayOfWeek(4);
        LocalDate adayago = today.minusDays(1);
        System.out.println(adayago + " - removed one day");
        LocalDate twodaysago = adayago.minusDays(1);
        System.out.println(twodaysago + " - removed one day");
        LocalDate threedaysago = twodaysago.minusDays(1);
        System.out.println(threedaysago + " - removed one day");
        LocalDate fourdaysago = threedaysago.minusDays(1);
        System.out.println(fourdaysago + " - removed one day");
        LocalDate fivedaysago = fourdaysago.minusDays(1);
        System.out.println(fivedaysago + " - removed one day");
        LocalDate sixdaysago = fivedaysago.minusDays(1);
        System.out.println(sixdaysago + " - removed one day");
        LocalDate lastWeek = sixdaysago.minusDays(1);

        week = lastWeek.getWeekOfWeekyear();
        year = lastWeek.getWeekyear();
        System.out.println(lastWeek + " - Removed one full week");
    }

    public void forwardOneWeek() {
        LocalDate today =
            new LocalDate().withWeekyear(year).withWeekOfWeekyear(week).withDayOfWeek(4);
        LocalDate tomorrow = today.plusDays(1);
        System.out.println(tomorrow + " - added one day");
        LocalDate dayAfterTomorrow = tomorrow.plusDays(1);
        System.out.println(dayAfterTomorrow + " - added one day");
        LocalDate threeDaysFromNow = dayAfterTomorrow.plusDays(1);
        System.out.println(threeDaysFromNow + " - added one day");
        LocalDate fourDaysFromNow = threeDaysFromNow.plusDays(1);
        System.out.println(fourDaysFromNow + " - added one day");
        LocalDate fiveDaysFromNow = fourDaysFromNow.plusDays(1);
        System.out.println(fiveDaysFromNow + " - added one day");
        LocalDate sixDaysFromNow = fiveDaysFromNow.plusDays(1);
        System.out.println(sixDaysFromNow + " - added one day");
        LocalDate nextWeek = sixDaysFromNow.plusDays(1);

        week = nextWeek.getWeekOfWeekyear();
        year = nextWeek.getWeekyear();
        System.out.println(nextWeek + " - Added one week");
    }

    public void thisWeek() {
        LocalDate thisWeek =
            new LocalDate().withWeekyear(year).withWeekOfWeekyear(week).withDayOfWeek(4);
        System.out.println(thisWeek + " - This is the current week");
    }

    public static void main(String[] args) {
        WonkyWeeks wonky = new WonkyWeeks();
        wonky.week = 2;
        wonky.year = 2015;
        wonky.thisWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.backUpOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
        wonky.forwardOneWeek();
    }
}
更改代码的输出:

2015-01-08 - This is the current week
2015-01-07 - removed one day
2015-01-06 - removed one day
2015-01-05 - removed one day
2015-01-04 - removed one day
2015-01-03 - removed one day
2015-01-02 - removed one day
2015-01-01 - Removed one full week
2014-12-31 - removed one day
2014-12-30 - removed one day
2014-12-29 - removed one day
2014-12-28 - removed one day
2014-12-27 - removed one day
2014-12-26 - removed one day
2014-12-25 - Removed one full week
2014-12-24 - removed one day
2014-12-23 - removed one day
2014-12-22 - removed one day
2014-12-21 - removed one day
2014-12-20 - removed one day
2014-12-19 - removed one day
2014-12-18 - Removed one full week
2014-12-17 - removed one day
2014-12-16 - removed one day
2014-12-15 - removed one day
2014-12-14 - removed one day
2014-12-13 - removed one day
2014-12-12 - removed one day
2014-12-11 - Removed one full week
2014-12-12 - added one day
2014-12-13 - added one day
2014-12-14 - added one day
2014-12-15 - added one day
2014-12-16 - added one day
2014-12-17 - added one day
2014-12-18 - Added one week
2014-12-19 - added one day
2014-12-20 - added one day
2014-12-21 - added one day
2014-12-22 - added one day
2014-12-23 - added one day
2014-12-24 - added one day
2014-12-25 - Added one week
2014-12-26 - added one day
2014-12-27 - added one day
2014-12-28 - added one day
2014-12-29 - added one day
2014-12-30 - added one day
2014-12-31 - added one day
2015-01-01 - Added one week
2015-01-02 - added one day
2015-01-03 - added one day
2015-01-04 - added one day
2015-01-05 - added one day
2015-01-06 - added one day
2015-01-07 - added one day
2015-01-08 - Added one week

我建议将您的示例代码缩减到复制此行为所需的基本内容。(当你这样做的时候,你可能会发现你自己的逻辑中有一个bug)@b战神它怎么可能被进一步分解呢?代码所做的一切就是创建一个
LocalDate
的实例,将其设置为一年中的第二个星期四,然后使用Joda提供的
plus
plus
方法进行前滚和后滚?或者更确切地说,它创建了相当多的实例,但我认为所有这些都是一样的?就我目前为止的推理而言,问题必须是Joda,与12-24和01-01的具体日期有关。我使用相同的方法(
backUpOneWeek()
forwardOneWeek()
)向前和向后滚动每个“周”。如果问题出在我的程序逻辑上,那么错误不应该在每个方法调用中重现吗?您可以通过设置一个日期,然后按设定的数量向前滚动,而不是链接一堆“添加时间”和“删除时间”调用来重现行为吗?您所看到的行为可能是由于添加了“天”的间隔而导致的,但toString方法不考虑闰秒。(有些日子实际上比24*60*60秒长)解释得很好。我试图收集我的答案中的所有信息,但找不到比你更好的+哇,解释得真不错!非常感谢!向上投票并正确回答!=)