我希望根据LocalDate.now()获取一周中第一天的日期。使用JodaTime可以实现以下功能,但似乎已从Java 8中的新Date API中删除。
LocalDate now = LocalDate.now();
System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY));
我无法拨打带有DayOfWeek()',因为它不存在。
所以我的问题是:如何根据某些LocalDate获取一周中第一天的日期?
答案 0 :(得分:64)
请注意,表达式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)
另一个例子是由于下面的评论:
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)
忽略了这个本地化问题。
答案 1 :(得分:15)
尝试
System.out.println(now.with(DayOfWeek.MONDAY));
答案 2 :(得分:3)
尽管有以前的答案,我仍然需要深入研究Java8正在做什么,所以我发现这是最直观的方法:
LocalDate实现Temporal
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());
first day of week (0 or 1) == 1
我必须确定我的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());
default zone offset==[Europe/London]
1st day of week==MONDAY
所以如果我根据这些默认值执行一些代码,就像这样:
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());
localDate == 2017-10-24
localdate first day of week == 2017-10-23 (MONDAY)
然后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());
configured localdate first day of week == 2017-10-22 (SUNDAY)
要获得更多信息,请查看LocalDate.with()
中的代码,这非常有趣。
答案 3 :(得分:2)
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day !
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
// get start of this week in milliseconds
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
System.out.println("Start of this week: " + cal.getTime());
System.out.println("... in milliseconds: " + cal.getTimeInMillis());
答案 4 :(得分:1)
正如Ray所说的correct Answer,您可以致电with
并传递DayOfWeek
枚举。
请注意,时区对于确定“今天”的日期至关重要。在任何时候,日期都会因您站在地球上的位置而异。
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate firstDayOfThisWeek = LocalDate.now ( zoneId ).with ( DayOfWeek.MONDAY );
如果未指定时区,则会以静默方式应用JVM的当前默认时区。注意:默认情况下,运行期间可随时更改更好地指定your desired/expected time zone。
ZonedDateTime
您可以将时区(ZoneId
)应用到LocalDate
,以获得代表一周中第一时刻的ZonedDateTime
。
ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );
答案 5 :(得分:1)
LocalDate似乎没有这个,但WeekFields(来自java-8 API)确实(here)。所以你可以这样做:
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
}
输入输出示例:
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
}
}
顺便说一句,奇怪的是我认为新API背后的代码实际上使用了Calendar类......
如果你不喜欢使用dayOfWeek用于LocalDate(和我一样),而你更喜欢用于Calendar的那个,你可以使用这些简单的转换器:
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
}
}
答案 6 :(得分:0)
有了Joda Time,你怎么看
now.toString("EEEE", locale)
答案 7 :(得分:0)
如果我想将星期一作为当前一周的第一天,它对我有用:
LocalDate mondayDate = LocalDate.now().with(WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
答案 8 :(得分:0)
wsCopy.Cells(lCopyLastRow, "A").Resize(1, 8).Copy _
wsDest.Range("A" & lDestLastRow)