gpt4 book ai didi

java - 如何获得几个日期之间正确的月数和天数?

转载 作者:行者123 更新时间:2023-12-01 19:41:04 25 4
gpt4 key购买 nike

我需要计算间隔列表之间正确的月数和天数:

31/03/2017  30/09/2017
01/10/2017 31/03/2018
01/04/2018 30/09/2018
01/10/2018 31/12/2019


如果我计算这些间隔之间的所有天数,然后除以30,我得到

MONTHS: 33 DAYS: 12


但我想要的是:

MONTHS: 33 DAYS: 1 (the only day to compute is the first day of first interval)

最佳答案

Answer by Ole V.V.是正确的,并且明智地使用了现代的java.time类。

LocalDateRange

作为奖励,我将提到在您的项目中添加出色的ThreeTen-Extra库以访问LocalDateRange类。此类将时间跨度表示为一对LocalDate对象。这似乎与您的业务问题匹配。

LocalDate start = … ;
LocalDate stop = … ;
LocalDateRange range = LocalDateRange.of( start , stop ) ;


从该 LocalDateRange对象中,您可以获取该 Answer by Ole V.V.中使用的 Period对象

Period period = range.toPeriod() ;


请注意, LocalDateRange具有方便进行比较的方法,例如 abutscontainsoverlaps等。

半开

您可能对如何处理月末/月初感到困惑。

通常,在日期时间处理中,最好使用Half-Open方法表示时间跨度。在这种方法中,开始是包含在内的,而结尾是排斥的。

因此,一个月从该月的第一天开始,一直持续到下个月的第一天,但​​不包括在内。

LocalDateRange rangeOfMonthOfNovember2019 = 
LocalDateRange.of(
LocalDate.of( 2019 , Month.NOVEMBER , 1 ) ,
LocalDate.of( 2019 , Month.DECEMBER , 1
)
;


您可以询问每个 LocalDateRange经过的天数: LocalDateRange::lengthInDays

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
List < LocalDateRange > ranges = new ArrayList <>( 4 );
ranges.add(
LocalDateRange.of(
LocalDate.parse( "31/03/2017" , f ) ,
LocalDate.parse( "30/09/2017" , f )
)
);
ranges.add(
LocalDateRange.of(
LocalDate.parse( "01/10/2017" , f ) ,
LocalDate.parse( "31/03/2018" , f )
)
);
ranges.add(
LocalDateRange.of(
LocalDate.parse( "01/04/2018" , f ) ,
LocalDate.parse( "30/09/2018" , f )
)
);
ranges.add(
LocalDateRange.of(
LocalDate.parse( "01/10/2018" , f ) ,
LocalDate.parse( "31/12/2019" , f )
)
);

// Sum the periods, one from each range.
Period period = Period.ZERO;
int days = 0;
for ( LocalDateRange range : ranges )
{
days = ( days + range.lengthInDays() );
period = period.plus( range.toPeriod() ).normalized();
}


转储到控制台。

System.out.println( "ranges: " + ranges );
System.out.println( "days: " + days + " | pseudo-months: " + ( days / 30 ) + " and days: " + ( days % 30 ) );
System.out.println( "period: " + period );



  范围:[2017-03-31 / 2017-09-30,2017-10-01 / 2018-03-31,2018-04-01 / 2018-09-30,2018-10-01 / 2019-12-31 ]
  
  天:1002 |伪月:33,天:12
  
  期间:P2Y5M119D


如果您坚持全封闭而不是半开放,则 LocalDateRange仍可以通过其 ofClosed方法为您提供帮助。但是我强烈建议您改用半开放式,因为我相信您会发现,在所有代码中使用一致的方法将使您的工作更加轻松。并教育您的用户。我看到办公室工作人员在对包含/不包含日期进行错误的假设时感到很困惑。您跟踪月末至月末的做法似乎会引起越来越多的困惑。

YearMonth

您可能会发现有用的另一个类内置于Java中: YearMonth。此类表示整个特定月份。

YearMonth yearMonth = YearMonth.of( 2019 , Month.NOVEMBER ) ;


注意诸如 atDay之类的方法,可从 LocalDate产生 YearMonth

ISO 8601

提示:将日期时间值序列化为文本时,养成仅使用ISO 8601标准格式而不是本地化格式的习惯。

因此,对于日期,请使用YYYY-MM-DD。

解析/生成文本时,java.time类默认使用这些格式。因此,无需指定格式化模式。

LocalDate.parse( "2019-01-23" ) 


整个月的标准ISO 8601格式为YYYY-MM,例如 2019-11

YearMonth yearMonth = YearMonth.parse( "2019-11" ) ;  // Entire month of November 2019.




关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧 legacy日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参见 Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为 JSR 310

现在位于 Joda-Time中的 maintenance mode项目建议迁移到 java.time类。

您可以直接与数据库交换java.time对象。使用与 JDBC driver或更高版本兼容的 JDBC 4.2。不需要字符串,不需要 java.sql.*类。

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。


Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


大多数java.time功能都被反向移植到 ThreeTen-Backport中的Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于较早的Android(<26), ThreeTenABP项目改编为 ThreeTen-Backport(如上所述)。请参见 How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuartermore

关于java - 如何获得几个日期之间正确的月数和天数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55383799/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com