java用date获取星期几_根据Java 8中的LocalDate.now()获取星期几的日期

我想根据LocalDate.now()获取一周中第一天的日期。 JodaTime可以进行以下操作,但似乎已从Java 8的新Date API中删除。

LocalDate now = LocalDate.now();

System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY));

我无法调用" withDayOfWeek()",因为它不存在。

所以我的问题是:如何基于某些LocalDate获取星期几的日期?

请注意,表达式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)忽略了此本地化问题。

仅供参考,WeekFields.of(Locale.getDefault()).getFirstDayOfWeek()返回当前语言环境的配置的一周的第一天(例如SUNDAY,MONDAY等)。不是日期。

@MenoHochschild为什么枚举DayOfWeek??在某些地区(例如美国)不起作用?有什么问题

@BasilBourque如果今天是星期日,并且我们在美国(星期天作为一周的第一天),则today.with(MONDAY)将转到第二天(+1),但是如果我们在欧洲,则需要返回6天(-6) 。表达式with(day-of-week)表示要在SAME日历周内进入星期几,这取决于星期几。

@BasilBourque为澄清起见,我之前的评论与WeekFields的使用有关(希望说with(day-of-week, 1))。如果您使用首选方法(基于enum-with(MONDAY)),则该操作仅基于ISO样式,假定始终将星期一作为一周的第一天。不幸的是,WeekFields不能直接用于枚举,而只能用于较长的数字(错误的设计),因此它比应使用的便捷性和秘密性更高(today.with(WeekFields.of(Locale.US).dayOfWeek(), MONDAY)无法编译)。

@MenoHochschild我对您的评论和声明now.with(DayOfWeek.MONDAY)在美国无法使用感到有些困惑。我有一个使用with(DayOfWeek.SUNDAY)的测试用例,并在今天(星期五)使用en_US区域设置和PST时区(-Duser.language=en -Duser.country=US -Duser.timezone=AmericaLos_Angeles)或欧洲区域设置和时区运行它,这给我带来了始终相同的结果-在两种情况下,我都越来越下一个星期日(8月20日),我想您要说的是美国时区(因为它是本周的一部分),所以我会在上个星期日得到。你能澄清一下吗?

@barthand首先,时区在这里根本不相关,仅与语言环境相关。但是,如果仅应用with(DayOfWeek.SUNDAY),那么语言环境也会被忽略,并且日期(如果不是星期日)将始终向前跳转,因为星期日是ISO-8601中的一周的最后一天。

@MenoHochschild感谢您的回答!因此,由于with(DayOfWeek)始终使用ISO-8601并忽略语言环境,因此这意味着with(DayOfWeek.MONDAY)始终会向后跳到上一个星期一(如果是星期一以外的任何一天),或者将保留在同一天(如果日期指向已经是星期一),对吗?

@barthand确实如此。

@MenoHochschild因此,也许有必要在您的答案中对其进行解释-请注意,表达式System.out.println(now.with(DayOfWeek.MONDAY));在美国或其他一些国家或地区将不起作用。有点误导,因为实际上它在美国和其他任何国家都可以以相同的方式(只是非本地化)工作。

@barthand感谢您的提示。我现在已经更新了第一句话/句子,希望现在可以更清楚。

您如何准确地获取当前语言环境的firstDayOfWeek而不是指定它?

@androiddeveloper参见javadoc

@MenoHochschild您的意思是:WeekFields.of(Locale.getDefault())。firstDayOfWeek吗?如果是这样,为什么不将其发布为真实答案?另外,我认为幕后的代码实际上仍然使用Calendar类,所以最好改用Calendar类...

@androiddeveloper是的,根据您的评论,我的意思是WeekFields.of(Locale.getDefault()).getFirstDayOfWeek(),但这不是OP的问题的答案,OP要求提供本周第一天的完整日历日期。

@MenoHochschild好了,所以我实际上在这里创建了一个答案:stackoverflow.com/a/48150270/878126

尝试

System.out.println(now.with(DayOfWeek.MONDAY));

我只是想补充一点,并不是地球上的所有地方都具有同一周的开始日期。如果需要,可以通过Calendar#getFirstDayOfWeek获得

我们能否以某种方式将星期更改为从星期日开始,并使用相同的命令获取星期的第一天?

无法正确处理区域设置,并非所有区域设置都以星期一作为一周的第一天开始。

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

LocalDate implements Temporal

with(TemporalField field, long newValue)

Returns an object of the same type as this object with the specified field altered.

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

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

System.out.printf("first day of week (0 or 1) == %d

",

ChronoField.DAY_OF_WEEK.range().getMinimum());

first day of week (0 or 1) == 1

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

System.out.printf("default zone offset==[%s]

",

ZoneId.systemDefault());

System.out.printf("1st day of week==%s

",

WeekFields.of(Locale.getDefault()).getFirstDayOfWeek());

default zone offset==[Europe/London]

1st day of week==MONDAY

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

LocalDate localDate = LocalDate.now();

System.out.printf("localDate == %s

", localDate);

System.out.printf("localdate first day of week == %s (%s)

",

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)

",

localDate.with(myWeek, 1),

localDate.with(myWeek, 1).getDayOfWeek());

configured localdate first day of week == 2017-10-22 (SUNDAY)

要了解更多信息,请查看LocalDate.with()中的代码,这很有趣。

感谢来自这个问题。

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());

感谢您的注意!但是,我一直在寻找使用LocalDate的Java 8方法。

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

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

LocalDate似乎没有此功能,但是WeekFields(来自Java-8 API)具有(此处)。因此,您可以执行以下操作:

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类。

如果您讨厌使用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

}

}

正如Ray的正确答案所说,您可以调用with并传递DayOfWeek枚举。

时区

请注意,时区对于确定"今天"的日期至关重要。在任何时候,日期都会因您在地球上的位置而异。

ZoneId zoneId = ZoneId.of ("America/Montreal" );

LocalDate firstDayOfThisWeek = LocalDate.now ( zoneId ).with ( DayOfWeek.MONDAY );

如果您未指定时区,则将静默应用JVM的当前默认时区。当心:该默认值可以在运行时随时更改!最好指定您想要的/预期的时区。

ZonedDateTime

您可以将时区(a ZoneId)应用于LocalDate,以获得表示一周中第一时刻的ZonedDateTime。

ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );

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());

}

有了Joda Time,您如何看待

now.toString("EEEE", locale)

我在javadoc中没有看到这样的方法。 docs.oracle.com/javase/8/docs/api/java/time/

我不好的是,这是一个乔达时间方法,我应该精确

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值