在 Java 8 中根据 LocalDate.now() 获取一周的第一天的日期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28450720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get date of first day of week based on LocalDate.now() in Java 8
提问by bashoogzaad
I would like the get the date of the first day of the week based on LocalDate.now(). The following was possible with JodaTime, but seems to be removed from the new Date API in Java 8.
我想根据 LocalDate.now() 获取一周的第一天的日期。JodaTime 可以实现以下功能,但似乎已从 Java 8 中的新 Date API 中删除。
LocalDate now = LocalDate.now();
System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY));
I can not call 'withDayOfWeek()', because it does not exist.
我不能调用 'withDayOfWeek()',因为它不存在。
So my question is:How to get the date of the first day of the week based on some LocalDate?
所以我的问题是:如何根据某个 LocalDate 获取一周的第一天的日期?
采纳答案by Meno Hochschild
Note that the expression System.out.println(now.with(DayOfWeek.MONDAY))
is locale-independent as it uses ISO-8601, therefore it always jumps backwards to last Monday (or stays on Monday in case date points to Monday already).
请注意,该表达式System.out.println(now.with(DayOfWeek.MONDAY))
与语言环境无关,因为它使用 ISO-8601,因此它总是向后跳转到上一个星期一(或者如果日期已经指向星期一,则保留在星期一)。
As such in US or some other countries - where week starts on Sunday - it may not work as you would expect - now.with(DayOfWeek.MONDAY)
will not jump forwardto Monday, in case date points to Sunday.
因此,在美国或其他一些国家/地区 - 一周从周日开始 - 它可能不会像您预期的那样工作 -now.with(DayOfWeek.MONDAY)
不会跳到周一,以防日期指向周日。
In case you need to address these concerns, it is better to use the localized field WeekFields.dayOfWeek():
如果您需要解决这些问题,最好使用本地化字段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)
Another example due to comments below:
另一个例子是由于下面的评论:
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
The US-example makes pretty clear that someone residing in US would expect to go to last and not to next Sunday because Sunday is considered as first day of week in US. The simple ISO-based expression with(DayOfWeek.SUNDAY)
ignores this localization issue.
美国的例子很清楚地表明,居住在美国的人会希望去最后一个星期天而不是下一个星期天,因为星期天在美国被认为是一周的第一天。简单的基于 ISO 的表达式with(DayOfWeek.SUNDAY)
忽略了这个本地化问题。
回答by Ray
Try
尝试
System.out.println(now.with(DayOfWeek.MONDAY));
回答by Semih Eker
Thanks to come fromin this question.
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());
回答by Basil Bourque
As the correct Answerby Ray says, you can call with
and pass the DayOfWeek
enum.
正如Ray的正确答案所说,您可以调用with
并传递DayOfWeek
枚举。
Time zone
时区
Note that time zone is crucial in determining the date of "today". At any moment the date varies by where you are standing on the globe.
请注意,时区对于确定“今天”的日期至关重要。在任何时候,日期都会因您在地球上的位置而异。
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate firstDayOfThisWeek = LocalDate.now ( zoneId ).with ( DayOfWeek.MONDAY );
If you do not specify a time zone, the JVM's current default time zone is silently applied. Beware: That default can change at any moment during runtime!Better to specify your desired/expected time zone.
如果您不指定时区,则会静默应用 JVM 的当前默认时区。当心:该默认值可以在运行时随时更改!最好指定您想要/预期的时区。
ZonedDateTime
ZonedDateTime
You can apply a time zone (a ZoneId
) to your LocalDate
to get a ZonedDateTime
representing the first moment of the week.
您可以将时区 (a ZoneId
) 应用于您的时区LocalDate
以获取ZonedDateTime
代表一周中的第一个时刻。
ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );
回答by Labe
With Joda Time, what do you think of
有了乔达时间,你怎么看
now.toString("EEEE", locale)
回答by Adam
Despite all the previous answers, I still had to dig around to work out what Java8 was doing, so here is what I found to be the most intuitive way of doing it:
尽管有所有以前的答案,我仍然需要深入研究 Java8 在做什么,所以这是我发现的最直观的方法:
LocalDate implements Temporal
with(TemporalField field, long newValue)
Returns an object of the same type as this object with the specified field altered.
LocalDate 实现Temporal
with(TemporalField field, long newValue)
返回与此对象具有相同类型的对象,并更改了指定的字段。
So we have to tell it which date part of LocalDate
we want to change (DAY_OF_WEEK
) and change to what value.
所以我们必须告诉它LocalDate
我们想要更改 ( DAY_OF_WEEK
) 的哪个日期部分并更改为什么值。
In case you had doubts that the days in the week might be counted from 0 to 6 or from 1 to 7:
如果您怀疑一周中的天数可能从 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
I had to nail down what my JDK was providing for defaults - YMMV:
我必须确定我的 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
So if I execute some code based on these defaults, like so:
因此,如果我根据这些默认值执行一些代码,如下所示:
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)
then Java goes with ChronoField.DAY_OF_WEEK
which not only defines which part of the date we want to alter, but also how to alter it.
然后 JavaChronoField.DAY_OF_WEEK
不仅定义了我们想要更改日期的哪一部分,而且还定义了如何更改它。
So if we want our code to deal with whatever the user specifies as the first day of the week, we create our own definition of how week-based calculations are meant to be done, using the WeekFields.of()
factory method.
因此,如果我们希望我们的代码处理用户指定为一周的第一天的任何内容,我们可以使用WeekFields.of()
工厂方法创建我们自己的基于周计算的定义。
Using this we can pass in our own dayOfWeek
parameter to with()
to do the date calculation the way we want:
使用它,我们可以传入我们自己的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)
For more insight, have a look at the code in LocalDate.with()
, it's quite interesting.
如需更多信息,请查看 中的代码LocalDate.with()
,它非常有趣。
回答by android developer
The LocalDate doesn't seem to have this, but WeekFields (which is from the java-8 API) does (here). So you can do this:
LocalDate 似乎没有这个,但是 WeekFields(来自 java-8 API)有(这里)。所以你可以这样做:
WeekFields.of(Locale.getDefault()).firstDayOfWeek.value
This returns the value of the first day of week, starting from 1 as Monday, ending with 7 as Sunday.
这将返回一周中第一天的值,从 1 开始作为星期一,以 7 结束作为星期日。
Example of usage (in Kotlin), to get a new LocalDate that has the dayOfWeek be set, going backward in time instead of forward:
使用示例(在 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
}
Example inputs-outputs :
示例输入输出:
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
And here's a sample function to go forward in time to the target day of week:
这是一个示例函数,可以及时前进到一周中的目标日期:
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
}
}
BTW, weird thing is that I think the code behind the scenes of the new API actually uses Calendar class anyway...
顺便说一句,奇怪的是,我认为新 API 的幕后代码实际上使用了 Calendar 类......
In case you hate using the dayOfWeek as used for LocalDate (as I do), and you prefer the one used with Calendar, you can use these simple converters:
如果您讨厌使用用于 LocalDate 的 dayOfWeek(就像我一样),并且您更喜欢与 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
}
}
回答by Taras Melnyk
It works for me in case if I want to get Mondayas a first day of current week:
如果我想将星期一作为本周的第一天,它对我有用:
LocalDate mondayDate = LocalDate.now().with(WeekFields.of(Locale.FRANCE).getFirstDayOfWeek());
回答by Narasimha Rao MNL
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());
}