【问题标题】:How do I increment calendar by 7 days until next month, then year from a starting date in Java?如何将日历增加 7 天,直到下个月,然后从 Java 中的开始日期开始增加一年?
【发布时间】:2016-08-09 18:26:48
【问题描述】:

这个问题一直困扰着我。我用谷歌搜索了从当前日期开始在 java 中的增量,但我希望它从过去的某个日期开始。

例如,让我们以这种格式从这个日期开始:

“1986-09-20”

我怎样才能增加天数,使上面的例子变成“1986-09-27”,再增加一个,它就变成“1986-10-4”,直到它变成“ 1987-01-03"

我知道我可以在当天使用 += 7 增加日期,如果超过 30 则增加月份,但我不知道如何计算 30 或 31 或 2 月的闰日天。

我一直在查看日历的文档并注意到它可能包含解决方案,但我不知道如何/从哪里开始。

我希望结果格式为 yyyy-mm-dd 而不是 Java 日期格式,即 Day Month dd time time-zone yyyy

【问题讨论】:

  • 你有示例代码可以展示吗?
  • 我从 Jonny Henly 提供的链接中尝试了这段代码,但没有成功:String start = "1986-09-20"; LocalDate parsedDate = LocalDate.parse(start); LocalDate addedDate = parsedDate.plusDays(7); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-mm-dd"); String result = addedDate.format(formatter); System.out.println(result);
  • 您的问题令人困惑。星期几是问题吗?如果输入的日期是星期二,你想要下个月的第一个星期二吗?
  • @BasilBourque 不,不是下个月的第一个星期二。我想以我输入的格式增加 7 天,并继续这样做,同时在一个月内增加一个月。然后一旦达到最大月份,它将增加年份。

标签: java date calendar


【解决方案1】:

其他答案正确但已过时。

字符串 != 日期时间

我希望结果格式为 yyyy-mm-dd 而不是 Java 日期格式,即 Day Month dd time time-zone yyyy

您将日期时间值与表示该值的字符串混淆了。因此,不存在“Java 日期格式”之类的东西。您可以生成任意格式的字符串,或者以本地化格式自动生成。

您想要的输入字符串是标准的ISO 8601 格式。 java.time 类默认使用这些标准格式。

java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormatJoda-Time 团队还建议迁移到 java.time。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

大部分 java.time 功能在ThreeTen-Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中进一步适应 Android。

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 等等。

LocalDate

LocalDate 类表示没有时间和时区的仅日期值。

LocalDate start = LocalDate.parse( "1986-09-20" );

这门课可以做数学,根据需要添加年数和周数。

显然,您希望从下个月输入日期的星期几的第一次出现开始。 TemporalAdjuster 接口和TemporalAdjusters 类(注意复数)提供了这样的帮助。特别是TemporalAdjusters.nextOrSame( DayOfWeek ),其中DayOfWeek 是一周中7 天的方便enum

DayOfWeek dow = start.getDayOfWeek();
LocalDate monthLater = start.plusMonths( 1 );  // If day 29-31 not found in following month, the last day of month is used instead. So always next month, not two months out.
LocalDate firstOfNextMonth = monthLater.withDayOfMonth( 1 );
TemporalAdjuster adjuster = TemporalAdjusters.nextOrSame( dow );
LocalDate firstDayOfWeekOfNextMonth = firstOfNextMonth.with( adjuster );

一年后。

LocalDate yearLaterFromFirstDayOfWeekOfNextMonth = firstDayOfWeekOfNextMonth.plusYears( 1 );

字符串

要生成所需的 ISO 8601 标准格式的字符串,只需调用 toString()

String output = yearLaterFromFirstDayOfWeekOfNextMonth.toString();

循环

您可以通过使用各种 java.time 类上的 equalscompareToisEqualisBeforeisAfter 方法进行测试来循环日期时间值。

LocalDate ld = start;
while ( ! ld.isAfter( firstDayOfWeekOfNextMonth ) ) {
    String output = ld.toString();
    …
    // Prepare for next loop.
    ld = ld.plusWeeks( 1 );
}

我建议先确定您的边界日期,以保持业务逻辑清晰。然后每周进行循环,因为这对逻辑来说是附带的。将这两个问题(边界日期和逐周)混合在一起会让您的问题感到困惑。

【讨论】:

    【解决方案2】:

    以下是您要查找的内容吗?

    Calendar cal = Calendar.getInstance();
    cal.clear();
    cal.set(1986, 8, 20);
    int year = cal.get(Calendar.YEAR);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    while (year >= cal.get(Calendar.YEAR)) {
        cal.add(Calendar.DAY_OF_MONTH, 7);
        System.out.println(sdf.format(cal.getTime()));
    }
    

    输出:

    1986-09-27
    1986-10-04
    1986-10-11
    1986-10-18
    1986-10-25
    1986-11-01
    1986-11-08
    1986-11-15
    1986-11-22
    1986-11-29
    1986-12-06
    1986-12-13
    1986-12-20
    1986-12-27
    1987-01-03

    【讨论】:

    • 刚刚试了一下,效果很好。它会考虑闰年和 30 或 31 个月末日吗?
    • 据我所知,无论您是闰年还是一个月是 30 天还是 31 天,它都不应该发挥任何作用。 10 月和 12 月是 31 天,11 月是 30 天,从输出中可以看出,它正确地增加了。
    • 我问的原因是因为我要使用它很多年直到2006年。我上面发布的例子是一个小规模的例子。
    • GregorianCalendar 能否与您提供的代码一样好用?以防闰年等。
    • 没关系,只要测试过闰年的输出就可以了!
    【解决方案3】:

    如果可以,请使用Joda Time。它将使一切变得容易得多,并且可以处理闰年等问题。

    这是一个简单的例子:

    DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd");
    DateTime dateTime = dtf.parseDateTime("1986-09-20");
    
    DateTime result = dateTime.plusDays(7);
    System.out.println("Result: " + dtf.print(result));
    

    【讨论】:

    • 这并不是对 OP 问题的真正回答,它只是对图书馆偏好的陈述。在 Joda Time 中展示如何操作。
    • 我要试试这个,我会回来编辑这条评论
    • 刚刚用这段代码试了一下:org.joda.time.format.DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd"); DateTime dateTime = dtf.parseDateTime("1986-09-20"); Date result = dateTime.plusDays(7).toDate(); System.out.println("Result: " + result); 结果是这样的:Result: Sat Sep 27 00:00:00 PDT 1986 这不是我要找的格式。
    • 使用 dtf.print(dateTime.plusDays(7));
    • dtr.print 方法不起作用,因为它给出了不正确的类型错误。
    猜你喜欢
    • 2016-01-11
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多