当前位置: 首页 > 知识库问答 >
问题:

使用java.time包从给定的星期和年获取星期一日期

蒋永宁
2023-03-14

我想使用Java8包Java从给定的星期和年份中获取星期一日期。时间但在某种程度上,我面临着这个问题,因为它并没有返回正确的日期。

private LocalDate getDateFromWeekAndYear(final String week,final String year){
    LocalDate date = LocalDate.now();
    date = date.with(WeekFields.ISO.dayOfWeek(), 1);
    date = date.with(WeekFields.ISO.weekOfWeekBasedYear(), Long.parseLong(week));
    date = date.with(WeekFields.ISO.weekBasedYear(), Long.parseLong(year));

    return date;
}

例如:

  • 如果我通过周=1和年=2013那么日期是:2012-12-31。
  • 但是如果我通过了周=53和年=2015,那么日期是: 2014-12-29。我期待2014-12-28。

我是否有任何逻辑错误或其他问题?

共有3个答案

公孙高畅
2023-03-14
YearWeek.of ( 2013 , 1 ).atDay ( DayOfWeek.MONDAY )

你的期望不正确。2015-W53的星期一是2015-12-28,不是2014-12-28,而是2015年,而不是2014年。没有理由期待2014年。如果您需要更多解释,请编辑您的问题以解释您的想法。

您可能会对日历年和基于周的年份感到困惑。在ISO 8601对基于周的年份的定义中,第一周包含日历年的第一个星期四。这意味着我们在这几年之间有一些重叠。日历年的最后几天可能位于下一个基于周的年份。反之亦然,日历年的前几天可能位于前一周。

例如,您可以在下面的屏幕截图中看到,2012日历的最后一天(12月31日)是2013年第1周的第1周。在另一个屏幕截图中,我们看到了相反的情况,2016年日历的前三天(1月1日、2日、,

  • 2013-W01的星期一是2012-12-31

我建议在你的项目中添加三个额外的库,以利用YearWeek类。与其只传递年和周的整数,不如传递此类的对象。这样做会使您的代码更加自文档化,提供类型安全性,并确保有效值。

// Pass ( week-based-year-number, week-number ). *Not* calendar year! See the ISO 8601 standard.
YearWeek yw = YearWeek.of( 2013 , 1 ); 

你可以从那一周的任何一天提取。

LocalDate ld = yw.atDay( DayOfWeek.MONDAY );

让我们试试这种代码。

YearWeek yw1 = YearWeek.of ( 2013 , 1 );
LocalDate ld1 = yw1.atDay ( DayOfWeek.MONDAY );

YearWeek yw2 = YearWeek.of ( 2015 , 53 );
LocalDate ld2 = yw2.atDay ( DayOfWeek.MONDAY );

System.out.println ( "yw1: " + yw1 + " Monday: " + ld1 );
System.out.println ( "yw2: " + yw2 + " Monday: " + ld2 );

yw1:2013-W01星期一:2012-12-31

yw2:2015-W53星期一:2015-12-28

提示:要在Calendar.app中的Mac上查看这些ISO 8601标准周数字,请设置System首选项

孙正业
2023-03-14

首先,你需要计算一年中第一周的第一个星期一,然后简单地加上日期的7的倍数。

public static LocalDate firstMonday(int week, int year) {

    LocalDate firstMonOfFirstWeek = LocalDate.now()
            .with(IsoFields.WEEK_BASED_YEAR, year) // year
            .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 1) // First week of the year
            .with(ChronoField.DAY_OF_WEEK, 1); // Monday

    // Plus multi of 7
    return firstMonOfFirstWeek.plusDays( (week - 1) * 7);
}

public static void main(String[] args) {
    System.out.println(firstMonday(1, 2013)); // 2012-12-31
    System.out.println(firstMonday(53 ,2015 )); // 2015-12-28
}
韦安顺
2023-03-14

这比OP和大多数答案显示的部分无效期望要困难得多。

首先说:定义基于周的操作的正确顺序是非常重要的。OP首先应用了日操纵,然后是基于年的操纵。正确的做法是反过来!我将展示正确的helper方法实现:

public static void main(String... args) {
    System.out.println(
      getDateFromWeekAndYear("53", "2015")); // 2015-12-28, NOT 2014-12-28
    System.out.println(
      getDateFromWeekAndYear("53", "2015").get(WeekFields.ISO.weekOfWeekBasedYear())); // 53
    System.out.println(
      getDateFromWeekAndYear("53", "2014")); // 2014-12-29
    System.out.println(
      getDateFromWeekAndYear("53", "2014").get(WeekFields.ISO.weekOfWeekBasedYear())); // 1
}

private static LocalDate getDateFromWeekAndYear(final String week,final String year) {
    int y = Integer.parseInt(year);
    LocalDate date = LocalDate.of(y, 7, 1); // safer than choosing current date
    // date = date.with(WeekFields.ISO.weekBasedYear(), y); // no longer necessary
    date = date.with(WeekFields.ISO.weekOfWeekBasedYear(), Long.parseLong(week));
    date = date.with(WeekFields.ISO.dayOfWeek(), 1);

    return date;
}

如果您不遵守此特定订单,那么您有时确实会收到输入2015-W53的2014年日期(取决于当前日期)。

第二个问题:我也避免了以当前日期开始,以避免接近日历年的开始或结束(日历年!=以周为基础的一年),而是选择年中作为起点。

第三个问题是对2014年(以周为基础)第53周的宽大处理。它不存在,因为2014年只有52周!!!严格的算法应该识别和拒绝这样的输入。因此,我建议不要使用YearWeek.of(2014,53)(在外部库Threeten-Extra)导致2015年的第一周,也请参阅其javadoc。比如此宽大的处理要好

YearWeek yw = YearWeek.of(2014, 52);
if (yw.is53WeekYear()) {
  yw = YearWeek.of(2014, 53);
}

或者使用我自己的时间库Time4J中的代码(与YearWeek相比,其类CalendarWeek具有额外的i18n功能和额外的周算术):

CalendarWeek.of(2014, 53); // throws an exception
System.out.println(CalendarWeek.of(2014, 1).withLastWeekOfYear()); // 2014-W52

仅使用java.time-包:

使用这样的外部库至少有助于以透明的方式解决第一个问题。如果您不愿意添加额外的依赖项,那么您可以这样做来处理第53周(如果无效):

如果表达式周末字段。应用于helper方法的结果上的ISO. ousOfBookBasedYear()会产生值1,那么您就知道第53周是无效的。然后你可以决定是接受宽大处理还是抛出一个例外。但是无声调节这种无效的输入是恕我直言不好的设计。

 类似资料:
  • 问题内容: 我需要输出从当前日期开始的未来12个月的日期列表(仅星期一和星期二),如下所示: 2010年1月 星期二2010年1月12日 星期一2010 年1月18日 星期二2010 年1月19日 星期一2010 年1月25 日星期一2010年 2月2日 星期二2010 年2月8日 星期一2010年2月9日星期二2010 年 2月 15 日星期一2010年2月15日 星期二2010 年2月16日

  • 问题内容: 我想确定一个日期并计算出其星期数。 到目前为止,我有以下内容。它应该是42时返回24。 数字反转是巧合吗?还是我快到了? 问题答案: 今天,使用PHP的对象会更好: 这是因为in中,它是这样的: 因此,您的订单是错误的。

  • 问题内容: 如果可能的话,在以下情况下,我希望使用joda或非joda解决方案 假设我的一周从2012年5月2日开始,给定的当前日期为02/22/2011。我需要计算给定当前日期的星期开始和结束日期。因此,我的解决方案的星期应该从02/19开始,而星期在02/25结束。为简单起见,我将我的工作日设置为02/05/2011,但是可能是任何一天,我的工作日始终为7天。 我现有的代码如下,但似乎无法按预

  • 问题内容: 如何获得当前一周的星期一和星期五的日期? 我有以下代码,但是如果当前日期是星期日或星期六,则它将失败。 问题答案: 这些strtotime输入效果很好: 您需要做的就是将逻辑包装在一些if语句中。

  • 问题内容: 我目前有此代码: 这是Date对象的扩展。 我需要做同样的事情,但是让日历返回我从星期一开始而不是星期日的一周中的几天。 问题答案: 您只需要使用iso8601日历获取一周中的第一天,其中第一个工作日为星期一,并添加0至6天。尝试这样:

  • 问题内容: 我有一个日期,以及如何使所有日期都落在给定日期所属的一周的Java中? 有人可以帮我这个吗。 我正在尝试获取给定日期的星期日期,我已经解释了为什么这个问题不是重复的,请在评论前阅读。 问题答案: 您可以尝试以下方式, 输出值