基于Java8中的LocalDate.now()获取每周第一天的日期

基于Java8中的LocalDate.now()获取每周第一天的日期,java,java-8,Java,Java 8,我希望根据LocalDate.now()获取一周中第一天的日期。以下内容在JodaTime中是可能的,但似乎已从Java8中的新日期API中删除 LocalDate now = LocalDate.now(); System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY)); 我无法调用“withDayOfWeek()”,因为它不存在 所以我的问题是:如何根据某个LocalDate获取一周中第一天的日期 试试看 System.ou

我希望根据LocalDate.now()获取一周中第一天的日期。以下内容在JodaTime中是可能的,但似乎已从Java8中的新日期API中删除

LocalDate now = LocalDate.now();
System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY));
我无法调用“withDayOfWeek()”,因为它不存在

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

试试看

System.out.println(now.with(DayOfWeek.MONDAY));
多亏了我的帮助


请注意,表达式
System.out.println(now.with(DayOfWeek.MONDAY))
是独立于区域设置的,因为它使用ISO-8601,因此它总是向后跳到最后一个星期一(或者如果日期已经指向星期一,则保持在星期一)

同样地,在美国或其他一些国家,一周从周日开始,它可能不会像您预期的那样工作-
现在。如果日期指向周日,则使用(DayOfWeek.MONDAY)
将不会向前跳到周一

如果需要解决这些问题,最好使用本地化字段:

另一个由以下评论引起的示例:

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
美国的例子非常清楚地表明,居住在美国的人希望去最后一个星期天,而不是下个星期天,因为星期天在美国被视为一周的第一天。基于ISO的简单表达式
with(DayOfWeek.SUNDAY)
忽略了这个本地化问题。

正如Ray所说,您可以调用
with
并传递枚举

时区 请注意,时区对于确定“今天”的日期至关重要。在任何时刻,日期都会因你在地球上所处的位置而有所不同

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate firstDayOfThisWeek = LocalDate.now ( zoneId ).with ( DayOfWeek.MONDAY );
如果不指定时区,JVM的当前默认时区将以静默方式应用。注意:默认值在运行时的任何时刻都可能更改!最好具体说明一下

ZoneDateTime
您可以将时区(a)应用于一周中的第一个时刻,以获得代表一周中第一个时刻的a

ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );

有了乔达的时间,你觉得怎么样

now.toString("EEEE", locale)

尽管前面给出了所有的答案,但我仍然需要深入研究Java8在做什么,因此我发现以下是最直观的方法:

LocalDate实现

with(临时字段,长newValue)

返回与此对象类型相同且指定字段已更改的对象

因此,我们必须告诉它要更改
LocalDate
的哪个日期部分(
DAY\u of u WEEK
),并更改为什么值

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

System.out.printf(“每周第一天(0或1)=%d\n”,
ChronoField.DAY/OF/u WEEK.range().getMinimum());
每周第一天(0或1)==1
我必须明确我的JDK为默认值提供了什么-YMMV:

System.out.printf(“默认区域偏移量==[%s]\n”,
ZoneId.systemDefault());
System.out.printf(“每周第一天==%s\n”,
WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());
默认区域偏移==[欧洲/伦敦]
每周第一天==星期一
如果我根据这些默认值执行一些代码,比如:

LocalDate LocalDate=LocalDate.now();
System.out.printf(“localDate==%s\n”,localDate);
System.out.printf(“localdate每周第一天==%s(%s)\n”,
localDate.with(ChronoField.DAY/u周,1),
localDate.with(ChronoField.DAY_OF u WEEK,1.getDayOfWeek());
localDate==2017-10-24
localdate每周第一天==2017-10-23(星期一)
然后Java使用了ChronoField.DAY/OF\u WEEK,它不仅定义了我们要更改日期的哪一部分,还定义了如何更改日期

因此,如果我们想让我们的代码处理用户指定为每周第一天的任何内容,我们可以使用
WeekFields.of()
factory方法创建我们自己的定义,定义如何进行基于周的计算

使用此选项,我们可以将自己的
dayOfWeek
参数传递到
with()
以我们想要的方式进行日期计算:

TemporalField myWeek=WeekFields.of(DayOfWeek.SUNDAY,1.DayOfWeek();
System.out.printf(“配置的localdate每周第一天==%s(%s)\n”,
localDate.with(myWeek,1),
localDate.with(myWeek,1.getDayOfWeek());
configured localdate每周第一天==2017-10-22(星期日)

要了解更多信息,请查看
LocalDate中的代码。使用()
,这非常有趣。

LocalDate似乎没有这一点,但WeekFields(来自java-8API)有()。所以你可以这样做:

WeekFields.of(Locale.getDefault()).firstDayOfWeek.value
这将返回一周中第一天的值,从1开始为星期一,以7结束为星期天

使用示例(在Kotlin中),要获取设置了dayOfWeek的新LocalDate,请在时间上向后而不是向前:

/**@param targetDayOfWeek day of week to go to, starting from 1 as Monday (and 7 is Sunday) */
fun LocalDate.minusDaysToDayOfWeek(targetDayOfWeek: Int = WeekFields.of(Locale.getDefault()).firstDayOfWeek.value): LocalDate {
    //conversion so that Sunday is 0, Monday is 1, etc:
    val diffDays = (dayOfWeek.value % 7) - (targetDayOfWeek % 7)
    val result = when {
        diffDays == 0 -> this
        diffDays < 0 -> minusDays((7 + diffDays).toLong())
        else -> minusDays(diffDays.toLong())
    }
    return result
}
下面是一个示例函数,用于及时前进到每周的目标日期:

fun LocalDate.plusDaysToDayOfWeek(targetDayOfWeek: Int = getLastDayOfWeek()): LocalDate {
    val diffDays = (targetDayOfWeek % 7) - (dayOfWeek.value % 7)
    val result = when {
        diffDays == 0 -> this
        diffDays < 0 -> plusDays((7 + diffDays).toLong())
        else -> plusDays(diffDays.toLong())
    }
    return result
}

/**@return the  last day of week, when 1 is Monday ... 7 is Sunday) */
@JvmStatic
fun getLastDayOfWeek(firstDayOfWeek: DayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek): Int {
    return when (firstDayOfWeek) {
        DayOfWeek.MONDAY -> DayOfWeek.SUNDAY.value
        else -> firstDayOfWeek.value - 1
    }
}

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

LocalDate mondayDate = LocalDate.now().with(WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());

谢谢你注意到这一点!然而,我一直在寻找使用LocalDate的Java8方式,我只想补充一点,地球上并非所有地方都有相同的一周起始日。如果需要的话,我们可以通过某种方式来改变这个星期,从星期日开始,使用相同的命令来获得一周的第一天。不正确地处理该区域,不是所有的区域都从星期一开始,作为第一周的一周。最简洁的答案是IMO。如果OP需要考虑不同的区域,他也必须在Joda时间内完成。仅供参考(Locale.getDefault())。getFirstDayOfWeek()返回为当前区域设置配置的每周第一天(例如,
星期天
星期一
,等等)。不是日期。@MenoHochschild为什么枚举在某些地区(如美国)不起作用?有什么问题吗?@BasilBourque如果今天是星期天,我们在
2017-12-31 -> 2017-12-31
2018-01-01 -> 2017-12-31
2018-01-02 -> 2017-12-31
2018-01-03 -> 2017-12-31
2018-01-04 -> 2017-12-31
2018-01-05 -> 2017-12-31
2018-01-06 -> 2017-12-31
2018-01-07 -> 2018-01-07
2018-01-08 -> 2018-01-07
2018-01-09 -> 2018-01-07
2018-01-10 -> 2018-01-07
2018-01-11 -> 2018-01-07
2018-01-12 -> 2018-01-07
2018-01-13 -> 2018-01-07
2018-01-14 -> 2018-01-14
2018-01-15 -> 2018-01-14
fun LocalDate.plusDaysToDayOfWeek(targetDayOfWeek: Int = getLastDayOfWeek()): LocalDate {
    val diffDays = (targetDayOfWeek % 7) - (dayOfWeek.value % 7)
    val result = when {
        diffDays == 0 -> this
        diffDays < 0 -> plusDays((7 + diffDays).toLong())
        else -> plusDays(diffDays.toLong())
    }
    return result
}

/**@return the  last day of week, when 1 is Monday ... 7 is Sunday) */
@JvmStatic
fun getLastDayOfWeek(firstDayOfWeek: DayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek): Int {
    return when (firstDayOfWeek) {
        DayOfWeek.MONDAY -> DayOfWeek.SUNDAY.value
        else -> firstDayOfWeek.value - 1
    }
}
fun DayOfWeek.toCalendarDayOfWeek(): Int {
    return when (this) {
        DayOfWeek.SATURDAY -> Calendar.SATURDAY
        else -> (this.value + 1) % 7
    }
}

@JvmStatic
fun convertLocalDateDayOfWeekToCalendarDayOfWeek(localDateDayOfWeek: Int): Int {
    return when (localDateDayOfWeek) {
        DayOfWeek.SATURDAY.value -> Calendar.SATURDAY
        else -> (localDateDayOfWeek + 1) % 7
    }
}

@JvmStatic
fun convertFromCalendarDayOfWeekToLocalDateDayOfWeek(calendarDayOfWeek: Int): Int {
    return when (calendarDayOfWeek) {
        Calendar.SUNDAY -> DayOfWeek.SUNDAY.value
        else -> calendarDayOfWeek - 1
    }
}
LocalDate mondayDate = LocalDate.now().with(WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
public void getWeekFromADateOfAMonth(){
    String date = "2019-01-02T18:25:43.511Z";
    TemporalField fieldISO = WeekFields.of(Locale.US).dayOfWeek();
    ZonedDateTime dateTime = ZonedDateTime.parse(date);

    int week = dateTime.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
    int weekYear = dateTime.get ( IsoFields.WEEK_BASED_YEAR );

    System.out.println ( "now: " + dateTime + " is week: " + week + " of weekYear: " + weekYear );

    int startDate = dateTime.with(fieldISO,1).getDayOfMonth();
    int endDate = dateTime.with(fieldISO,7).getDayOfMonth();

    String startMonth = String.valueOf(dateTime.with(fieldISO,1).getMonth());
    String endMonth = String.valueOf(dateTime.with(fieldISO,7).getMonth());
}