获取本周第一天和当前时间之间的时间范围 JDK 8
Getting time range between the first day of current week and current time JDK 8
我可以很容易地计算出一个月的第一天和当前时间之间的时间段:
/**
* Returns the time range between the first day of month and current time in milliseconds.
*
* @param zoneId time zone ID.
* @return a {@code long} array, where at index: 0 - the first day of month midnight time; 1 - current time.
*/
public static long[] monthDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
ZonedDateTime startZdt = nowZdt.withDayOfMonth(1);
toReturn[0] = startZdt.toInstant().toEpochMilli();
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}
但是如何从本周的第一天(午夜)开始计数呢?
解决方法:
/**
* Returns the time range between the first day of current week midnight and current time in milliseconds.
*
* @param zoneId time zone ID.
* @return a {@code long} array, where at index: 0 - the first day of current week midnight time; 1 - current time.
*/
public static long[] monthDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
//ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);//As suggested by Basil Bourque (tested).
//ZonedDateTime startZdt = nowZdt.with(ChronoField.DAY_OF_WEEK, 1);
ZonedDateTime startZdt = nowZdt.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));//As suggested by Basil Bourque (tested).
startZdt = startZdt.toLocalDate ().atStartOfDay(zoneId);
toReturn[0] = startZdt.toInstant().toEpochMilli();
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}
tl;博士
ZonedDateTime
.now( ZoneId.of( "Asia/Kolkata" ) ) // Current moment in a particular time zone.
.toLocalDate() // Extract date-only value, losing the time-of-day and time zone components.
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) ) // Move to another day-of-week, or same date if this is the desired day-of-week.
.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) // Determine the first moment of the day. Do *not* assume this time-of-day is 00:00:00 as anomalies such as Daylight Saving Time (DST) may mean otherwise such as 01:00:00.
.toInstant() // Adjust into UTC, same moment, same point on the timeline, but viewed through the lens of UTC time zone.
.toEpochMilli() // Extract a count-from-epoch in milliseconds. I do *not* recommend tracking date-time this way, but the Question requires this number.
详情
很好,但这里有一个更直接和灵活的替代方法。
获取当前时刻作为 ZonedDateTime
。
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
TemporalAdjuster
TemporalAdjuster
界面允许您操作日期时间值以获得新的日期时间值。 TemporalAdjusters
class(注意复数 s
)提供了几个方便的实现。使用 DayOfWeek
枚举指定您认为哪一天是一周的第一天。
DayOfWeek dowStartOfWeek = DayOfWeek.MONDAY ;
LocalDate weekStartDate = now.toLocalDate().with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) ;
ZonedDateTime start = weekStartDate.atStartOfDay( z ) ; // Determine first moment of the day. Note: *not* always 00:00:00.
看到这个code run live at IdeOne.com。
2017-08-21T00:00+12:00[Pacific/Auckland]
2017-08-21T08:44:46.439+12:00[Pacific/Auckland]
时间跨度
为了报告您的时间跨度,如果需要,pou 确实可以提取整秒的计数。
long epochSeconds = start.toEpochSecond() ;
或通过Instant
提取毫秒数。
long epochMillis = start.toInstant().toEpochMilli() ;
但请记住,这两个数字都会截断任何进一步的小数秒,因为 java.time 类型解析为 nanoseconds。
除了截断之外,还有其他原因可以避免跟踪日期时间,因为 count-from-epoch. Since such values are meaningless to the human eye, debugging is much more difficult and faulty data may escape your notice. Also, you may assume the epoch is 1970-01-01T00:00:00Z
, but there are at least another couple dozen epochs 被常见的软件系统使用。另一个问题是计数的粒度不明确,有些系统使用整秒,有些系统使用毫秒,有些系统使用微秒,其他系统使用纳秒,还有一些系统使用其他分辨率。
Interval
因此,我建议不要只返回 long
整数,而是返回一个对象。一对 Instant
对象起作用,这是 Interval
class in the ThreeTen-Extra 项目使用的对象。 class 有几个非常方便的方法,我希望调用代码可能会觉得有用,例如 contains
、encloses
、abuts
、overlaps
、span
,isEmpty
,等等。
org.threeten.extra.Interval interval = Interval.of( start.toInstant() , now.toInstant() ) ;
您可以应用时区以通过区域自己的挂钟时间的镜头查看开始或结束。
ZonedDateTime zdtStart = interval.getStart().atZone( z ); // Or `getEnd()`.
我可以很容易地计算出一个月的第一天和当前时间之间的时间段:
/**
* Returns the time range between the first day of month and current time in milliseconds.
*
* @param zoneId time zone ID.
* @return a {@code long} array, where at index: 0 - the first day of month midnight time; 1 - current time.
*/
public static long[] monthDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
ZonedDateTime startZdt = nowZdt.withDayOfMonth(1);
toReturn[0] = startZdt.toInstant().toEpochMilli();
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}
但是如何从本周的第一天(午夜)开始计数呢?
解决方法:
/**
* Returns the time range between the first day of current week midnight and current time in milliseconds.
*
* @param zoneId time zone ID.
* @return a {@code long} array, where at index: 0 - the first day of current week midnight time; 1 - current time.
*/
public static long[] monthDateRange(ZoneId zoneId) {
long[] toReturn = new long[2];
//ZonedDateTime nowZdt = LocalDateTime.now().atZone(zoneId);
ZonedDateTime nowZdt = ZonedDateTime.now(zoneId);//As suggested by Basil Bourque (tested).
//ZonedDateTime startZdt = nowZdt.with(ChronoField.DAY_OF_WEEK, 1);
ZonedDateTime startZdt = nowZdt.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));//As suggested by Basil Bourque (tested).
startZdt = startZdt.toLocalDate ().atStartOfDay(zoneId);
toReturn[0] = startZdt.toInstant().toEpochMilli();
toReturn[1] = nowZdt.toInstant().toEpochMilli();
return toReturn;
}
tl;博士
ZonedDateTime
.now( ZoneId.of( "Asia/Kolkata" ) ) // Current moment in a particular time zone.
.toLocalDate() // Extract date-only value, losing the time-of-day and time zone components.
.with( TemporalAdjusters.previousOrSame( DayOfWeek.SUNDAY ) ) // Move to another day-of-week, or same date if this is the desired day-of-week.
.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) // Determine the first moment of the day. Do *not* assume this time-of-day is 00:00:00 as anomalies such as Daylight Saving Time (DST) may mean otherwise such as 01:00:00.
.toInstant() // Adjust into UTC, same moment, same point on the timeline, but viewed through the lens of UTC time zone.
.toEpochMilli() // Extract a count-from-epoch in milliseconds. I do *not* recommend tracking date-time this way, but the Question requires this number.
详情
获取当前时刻作为 ZonedDateTime
。
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
TemporalAdjuster
TemporalAdjuster
界面允许您操作日期时间值以获得新的日期时间值。 TemporalAdjusters
class(注意复数 s
)提供了几个方便的实现。使用 DayOfWeek
枚举指定您认为哪一天是一周的第一天。
DayOfWeek dowStartOfWeek = DayOfWeek.MONDAY ;
LocalDate weekStartDate = now.toLocalDate().with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) ;
ZonedDateTime start = weekStartDate.atStartOfDay( z ) ; // Determine first moment of the day. Note: *not* always 00:00:00.
看到这个code run live at IdeOne.com。
2017-08-21T00:00+12:00[Pacific/Auckland] 2017-08-21T08:44:46.439+12:00[Pacific/Auckland]
时间跨度
为了报告您的时间跨度,如果需要,pou 确实可以提取整秒的计数。
long epochSeconds = start.toEpochSecond() ;
或通过Instant
提取毫秒数。
long epochMillis = start.toInstant().toEpochMilli() ;
但请记住,这两个数字都会截断任何进一步的小数秒,因为 java.time 类型解析为 nanoseconds。
除了截断之外,还有其他原因可以避免跟踪日期时间,因为 count-from-epoch. Since such values are meaningless to the human eye, debugging is much more difficult and faulty data may escape your notice. Also, you may assume the epoch is 1970-01-01T00:00:00Z
, but there are at least another couple dozen epochs 被常见的软件系统使用。另一个问题是计数的粒度不明确,有些系统使用整秒,有些系统使用毫秒,有些系统使用微秒,其他系统使用纳秒,还有一些系统使用其他分辨率。
Interval
因此,我建议不要只返回 long
整数,而是返回一个对象。一对 Instant
对象起作用,这是 Interval
class in the ThreeTen-Extra 项目使用的对象。 class 有几个非常方便的方法,我希望调用代码可能会觉得有用,例如 contains
、encloses
、abuts
、overlaps
、span
,isEmpty
,等等。
org.threeten.extra.Interval interval = Interval.of( start.toInstant() , now.toInstant() ) ;
您可以应用时区以通过区域自己的挂钟时间的镜头查看开始或结束。
ZonedDateTime zdtStart = interval.getStart().atZone( z ); // Or `getEnd()`.