确定用Java中的时间范围表示的天数 [英] Determine number of days represented by a time range in Java

查看:383
本文介绍了确定用Java中的时间范围表示的天数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Java 8时间,我只是想弄清楚一个时间范围内表示的天数.请考虑以下内容:

Using Java 8 time I am simply trying to figure out the number of days represented in a time range. Consider the following:

LocalDate start = LocalDate.of(2016, Month.MARCH, 28);
LocalDate end = LocalDate.of(2016, Month.MARCH, 31);
Period period = Period.between(start, end);

期间中的天数为3,表示两个日期之间的天数,包括开始日期和结束日期.我想要的是由2个日期表示的天数,实际上是4个日期(3月28日,3月29日,3月30日,3月31日).

The number of days in period is 3 which represents the number of days between the 2 dates, inclusive of start and exclusive of end. What I want is the number of days represented by the 2 dates which is actually 4 (March 28, March 29, March 30, March 31).

我知道我可以将Period.between()返回的天数加1,但是我想我很惊讶我找不到另一个调用来完全返回我想要的.我缺少什么还是添加1是唯一的解决方案?

I know I can just add 1 to the number of days returned from Period.between() but I guess I was surprised that I couldn't find another call to return exactly what I want. Am I missing something or is adding 1 the only solution?

推荐答案

tl; dr

始终通过半开放 方法定义您的时间跨度,其中:

tl;dr

Always define your spans of time by the Half-Open approach where:

  • 开头是 .
  • 结局是排他性的 .

当需要四天的March 28, March 29, March 30, March 31时,将3月28日开始,将4月1日结束.直到第一天(3月28日)为止,一直运行到那些日期,但不包括,最后一个(4月1日).

When you want the four days of March 28, March 29, March 30, March 31, make the beginning March 28 and the ending April 1. Run through those dates starting at the first (March 28th) while going up to, but not including, the last (April 1st).

2016-03-28/2016-04-01

2016-03-28/2016-04-01

半开放

我错过了一些东西

Am I missing something

您可能会错过半开放式方法在定义时间跨度方面的有用性.

You may be missing an appreciation for the usefulness of the Half-Open approach in defining spans of time.

通常,定义时间跨度的最佳实践是半开放式方法.在Half-Open中,开头是包含,而结尾是包含.

Generally, the best practice for defining spans of time is the Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive.

此方法解决了处理小数秒的问题.凭直觉,许多程序员将尝试找到最后可能的时刻作为时间跨度的结束.但是最后一刻涉及到无限可分的最后一秒.您可能会想,好吧,只需将毫秒数保留到小数点后三位,午休时间结束时才移至12:59.59.999,因为这是我将需要的所有分辨率,而这就是旧版Java的分辨率.但是,您将无法在数据库中找到匹配项,例如Postgres,它以微秒的分辨率(12:59:59.999999)存储日期-时间值.因此,您决定使用分数的六个小数位x .999999.但是开始在java.time类中遇到了与日期时间值不匹配的问题,并且您学习到了提供的纳秒分辨率(对于9位小数秒x.999999999的纳秒级).半开放式方法,其结尾将持续到下一秒,但不包括下一秒.

This approach solves the problem of dealing with fractional seconds. Intuitively, many programmers will try to find the last possible moment as the ending of a span of time. But that last moment involves an infinitely divisible last second. You might think, "Well, just go to three decimal place for milliseconds, 12:59.59.999 for the end of noon lunch break, as that is all the resolution I will ever need, and that is the resolution of the legacy java.util.Date class.". But then you would fail to find matches in your database like Postgres that store date-time values with a resolution of microseconds, 12:59:59.999999. So you decide to use six decimal places of fraction, x.999999. But the start experiencing mismatches with date-time values in the java.time classes, and you learn the offer a resolution of nanoseconds for nine digits of fractional second, x.999999999. You can disembark this carousel of frustrating bugs by using the Half-Open approach where the ending runs up to, but does not include, the next whole second.

我相信您会在整个日期时间处理代码(无论是否涉及小数秒)中一贯使用Half-Open方法:

I believe you will find consistent use of the Half-Open approach throughout your date-time handling code (whether fractional seconds may be involved or not) will:

  • 使您的代码更易于阅读和理解.
  • 从总体上减轻认知负担.
    知道所有时间跨度都相同,就可以消除歧义.
  • 减少错误.

示例:

  • 中午午餐时段从时钟中午(12:00:00)开始,一直到时钟中午1点为止.这意味着12:00:00到13:00:00.
  • 一整天从一天的第一时刻开始(
  • A noon lunch period starts at the moment the clock strikes noon (12:00:00) and runs up to, but does not include, the moment when the clock strikes one o’clock. That means 12:00:00 to 13:00:00.
  • A full day starts at the first moment of the day (not always 00:00:00, by the way) and runs up to, but does not include, the first moment of the following day.
  • A week starts on a Monday and runs up to, but does not include, the following Monday. That means seven days in Monday-Monday.
  • A month starts of the first of the month and runs up to, but not including, the first of the following month. So the month of March is March 1 to April 1.

而不是加一个1来获得总天数,而是将您的时间跨度定义为Half-Open :开始是包容性的,结束是包容性的.如果您要代表3月28日,29日,30日和31日这四个日期,则建议您定义从3月28日到4月1日的时间范围.

Rather than one adding 1 to get a total of days, define your span of time as Half-Open: beginning-is-inclusive, ending-is-exclusive. If you are trying to represent the four dates of March 28, 29, 30, and 31, then I suggest you define a span of time from March 28 to April 1.

LocalDate start = LocalDate.of( 2016, Month.MARCH, 28 ) ; // inclusive
LocalDate stop = LocalDate.of( 2016, Month.APRIL, 1 ) ; // exclusive

Period

java.time类明智地使用Half-Open方法.因此

Period

The java.time classes wisely use the Half-Open approach. So the Period.between method treats the ending as exclusive, as noted in the Question. I suggest you go-with-the-flow here rather than fight it. Search Stack Overflow for many more examples of how well this approach works.

Period p = Period.between( start , stop );

p.toString():P4D

p.toString(): P4D

ChronoUnit

如果您希望总天数,例如一个半月为45天,请使用此问题以进行讨论.

ChronoUnit

If you want a total number of days, such as 45 for a month and a half, use the ChronoUnit enum, an implementation of TemporalUnit. See this Question for discussion.

同样,java.time类使用Half-Open方法.所以

Again, the java.time classes use the Half-Open approach. So

long daysBetween = ChronoUnit.DAYS.between( start, stop );

4

实时代码

请参见下面的示例代码在IdeOne.com上实时运行.

这篇关于确定用Java中的时间范围表示的天数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆