根据Java 8中的LocalDate.now()获取一周的第一天的日期

bas*_*aad 47 java java-8

我希望根据LocalDate.now()得到一周中第一天的日期.使用JodaTime可以实现以下功能,但似乎已从Java 8中的新Date API中删除.

LocalDate now = LocalDate.now();
System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY));
Run Code Online (Sandbox Code Playgroud)

我不能称'withDayOfWeek()',因为它不存在.

所以我的问题是:如何根据一些LocalDate获取一周中第一天的日期?

Men*_*ild 76

请注意,表达式System.out.println(now.with(DayOfWeek.MONDAY))与区域设置无关,因为它使用ISO-8601,因此它总是向后跳到上周一(或者在星期一停留,以防日期已经指向星期一).

因此,在美国或其他一些国家 - 周日开始周 - 可能无法按预期工作 - 如果日期指向星期日,now.with(DayOfWeek.MONDAY) 则不会跳到周一.

如果您需要解决这些问题,最好使用本地化字段WeekFields.dayOfWeek():

LocalDate now = LocalDate.now();
TemporalField fieldISO = WeekFields.of(Locale.FRANCE).dayOfWeek();
System.out.println(now.with(fieldISO, 1)); // 2015-02-09 (Monday)

TemporalField fieldUS = WeekFields.of(Locale.US).dayOfWeek();
System.out.println(now.with(fieldUS, 1)); // 2015-02-08 (Sunday)
Run Code Online (Sandbox Code Playgroud)

另一个例子是由于下面的评论:

LocalDate ld = LocalDate.of(2017, 8, 18); // Friday as original date

System.out.println(
    ld.with(DayOfWeek.SUNDAY)); // 2017-08-20 (2 days later according to ISO)

// Now let's again set the date to Sunday, but this time in a localized way...
// the method dayOfWeek() uses localized numbering (Sunday = 1 in US and = 7 in France)

System.out.println(ld.with(WeekFields.of(Locale.US).dayOfWeek(), 1L)); // 2017-08-13
System.out.println(ld.with(WeekFields.of(Locale.FRANCE).dayOfWeek(), 7L)); // 2017-08-20
Run Code Online (Sandbox Code Playgroud)

美国的例子清楚地表明,居住在美国的人会期望持续到下周日,因为周日被认为是美国的第一天.简单的基于ISO的表达式with(DayOfWeek.SUNDAY)忽略了这个本地化问题.

  • @BasilBourque如果今天是星期天而我们在美国(星期日是星期几的第一天)那么`today.with(星期一)`将会到第二天(+1),但如果我们在欧洲那么我们将去6天回来(-6).表达式"with(day-of-week)"表示在SAME日历周内进入星期几,这取决于一周的开始. (6认同)
  • @MenoHochschild为什么enum [`DayOfWeek`](http://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html)在美国等某些语言环境中不起作用?有什么问题? (3认同)

Ray*_*Ray 19

尝试

System.out.println(now.with(DayOfWeek.MONDAY));
Run Code Online (Sandbox Code Playgroud)

  • 我想补充一点,并非地球上的所有地方都有相同的开始日期.如果它的需要,它可以通过获得[日历#getFirstDayOfWeek](http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getFirstDayOfWeek%28%29) (2认同)
  • 没有正确处理区域设置,并非所有区域设置都以星期一作为一周的第一天开始。 (2认同)

Ada*_*dam 5

尽管有所有先前的答案,我仍然必须深入研究Java8在做什么,所以这是我发现最直观的方法:

LocalDate实现临时的

with(TemporalField field, long newValue)

返回与此对象具有相同类型的对象,但更改了指定字段。

因此,我们必须告诉它LocalDate要更改(DAY_OF_WEEK)的日期部分并更改为哪个值。

如果您怀疑一周中的天数可能是从0到6或从1到7:

    System.out.printf("first day of week (0 or 1) == %d \n",
            ChronoField.DAY_OF_WEEK.range().getMinimum());
Run Code Online (Sandbox Code Playgroud)
first day of week (0 or 1) == 1 
Run Code Online (Sandbox Code Playgroud)

我必须弄清楚我的JDK提供的默认值-YMMV:

    System.out.printf("default zone offset==[%s]\n",
            ZoneId.systemDefault());
    System.out.printf("1st day of week==%s\n",
            WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
Run Code Online (Sandbox Code Playgroud)
default zone offset==[Europe/London]
1st day of week==MONDAY
Run Code Online (Sandbox Code Playgroud)

因此,如果我根据这些默认值执行一些代码,如下所示:

    LocalDate localDate = LocalDate.now();
    System.out.printf("localDate == %s \n", localDate);
    System.out.printf("localdate first day of week == %s (%s) \n",
            localDate.with(ChronoField.DAY_OF_WEEK, 1),
            localDate.with(ChronoField.DAY_OF_WEEK, 1).getDayOfWeek());
Run Code Online (Sandbox Code Playgroud)
localDate == 2017-10-24 
localdate first day of week == 2017-10-23 (MONDAY) 
Run Code Online (Sandbox Code Playgroud)

Java ChronoField.DAY_OF_WEEK不仅可以定义我们要更改日期的哪一部分,还可以定义如何更改日期。

因此,如果我们希望代码处理用户在一周的第一天指定的任何内容,那么我们将使用WeekFields.of()工厂方法来创建自己的定义,说明如何进行基于周的计算。

使用此dayOfWeek参数,我们可以传入我们自己的参数以with()所需的方式进行日期计算:

    TemporalField myWeek = WeekFields.of(DayOfWeek.SUNDAY, 1).dayOfWeek();
    System.out.printf("configured localdate first day of week == %s (%s) \n",
            localDate.with(myWeek, 1),
            localDate.with(myWeek, 1).getDayOfWeek());
Run Code Online (Sandbox Code Playgroud)
configured localdate first day of week == 2017-10-22 (SUNDAY) 
Run Code Online (Sandbox Code Playgroud)

要获得更多的见解,请看中的代码LocalDate.with(),这很有趣。


Tar*_*nyk 5

如果我想将星期一作为本周的第一天,它对我有用:

LocalDate mondayDate = LocalDate.now().with(WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
Run Code Online (Sandbox Code Playgroud)