gpt4 book ai didi

java - 在Java中获取两个日期之间的精确差异

转载 作者:行者123 更新时间:2023-11-30 10:34:10 24 4
gpt4 key购买 nike

我正在寻找一种方法来获得两个日期之间的差异,正如标题中所说的那样,在Java中。例如,如果d1 = 2017-01-23 05:25:00d2 = 2018-03-20 07:29:50,则将打印某些方法

Years: 1
Months: 1
Days: 25
Hours: 2
Minutes: 4
Seconds: 50


我尝试使用LocalDateTime对象来执行此操作,但是我找不到找到它们之间相隔几个月的方法。我看不到需要包含该代码,但是如果需要的话可以。我不在乎日期是什么类型,但是我不想使用Joda时间或其他外部库。预先感谢您的帮助。

最佳答案

ISO 8601

我们必须解析您的字符串。解析/生成字符串时,java.time类默认使用标准ISO 8601格式。您的投入接近合规;我们只需要用T替换中间的空格。

String inputStart = "2017-01-23 05:25:00".replace ( " " , "T" );
String inputStop = "2018-03-20 07:29:50".replace ( " " , "T" );


LocalDateTime

您的输入没有任何偏离UTC或时区的指示。因此,它们不代表时间轴上的实际时刻,仅代表时间轴上可能的时刻的模糊概念。因此,我们将其解析为 LocalDateTime对象。我们将用来确定时间跨度的数学将基于24小时通用天,并且将忽略诸如 Daylight Saving Time (DST)之类的异常。

LocalDateTime start = LocalDateTime.parse ( inputStart );
LocalDateTime stop = LocalDateTime.parse ( inputStop );


PeriodDuration

java.time类将未附加到时间轴的时间范围定义为两部分。 Period类表示年-月-日,而 Duration类表示小时-分钟-秒。

将时间跨度分成这两部分可以避免某些问题,这些问题是我们必须解决的问题。您究竟想如何在第一天处理可能的部分时间,并在结束时处理可能的部分时间?一天的中午到第二天的中午是一天还是24小时?如果我们将第一天的时间与最后一天的时间相加,那么如果该数字超过24小时,我们是否应该挤出一整天?

计算中

在这里,我采用了计算整天数的方法,而忽略了第一天和最后一天。然后,我将第一天的小时数与最后一天的小时数相加。正如我们从您的示例数据中看到的那样,这可能导致我们的 Duration超过24小时。这种方法可能会或可能不会满足您未曾陈述的意图/定义。

Period p = Period.between ( start.toLocalDate () , stop.toLocalDate () ).minusDays ( 1 );  // Subtract one, as we account for hours of first day.

// Get the Duration of first day's hours-minutes-seconds.
LocalDateTime startNextDay = start.toLocalDate ().plusDays ( 1 ).atStartOfDay ();
Duration dStart = Duration.between ( start , startNextDay );

// Get the Duration of first day's hours-minutes-seconds.
LocalDateTime stopStartOfDay = stop.toLocalDate ().atStartOfDay ();
Duration dStop = Duration.between ( stopStartOfDay , stop );

// Combine the pair of partial days into a single Duration.
Duration d = dStart.plus ( dStop );


转储到控制台。 toStringPeriod类上的 Duration方法在ISO 8601的 standard durations format中生成字符串: PnYnMnDTnHnMnS其中 P标记开始,而 T将年月日与小时分开-分钟-秒。

System.out.println ( "start/stop: " + start + "/" + stop );
System.out.println ( "p: " + p );
System.out.println ( "dStart: " + dStart + " and dStop: " + dStop );
System.out.println ( "d: " + d );



  开始/停止:2017-01-23T05:25 / 2018-03-20T07:29:50
  
  p:P1Y1M24D
  
  dStart:PT18H35M和dStop:PT7H29M50S
  
  d:PT26H4M50S


为了获得所需的文本输出,您需要询问 Period的每个部分和 Duration的每个部分。

int years = p.getYears ();
int months = p.getMonths ();
int days = p.getDays ();


Java 8莫名其妙地缺少方便地从 Duration中获取小时,分钟或秒的部分的方法。 Java 9添加了此类方法。有关更多讨论,请参见 this Question

long durationDays = d.toDaysPart();
long hours = d.toHoursPart();
long minutes = d.toMinutesPart();
long seconds = d.toSecondsPart();
int nanos = d.toNanosPart();


现场代码

请参见以下示例 code working live in IdeOne.com



ZonedDateTime

上面的讨论是针对一般的24小时工作日,而忽略了从UTC /时区偏移的问题。

相反,如果要跟踪时间轴上的实际时刻,则必须应用用于这些日期时间字符串的时区。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = start.atZone( z );



其余代码类似,但是将 ZoneId传递给 atStartOfDay调用以生成 ZonedDateTime对象而不是 LocalDateTime对象。

请记住,使用 ZonedDateTime对象而不是 LocalDateTime对象时,您可能会获得不同的结果。

请参见示例 code live in IdeOne.com

String inputStart = "2017-01-23 05:25:00".replace ( " " , "T" );
String inputStop = "2018-03-20 07:29:50".replace ( " " , "T" );

LocalDateTime ldtStart = LocalDateTime.parse ( inputStart ); // LocalDateTime used only briefly here, to parse inputs. Then we switch to `ZonedDateTime`.
LocalDateTime ldtStop = LocalDateTime.parse ( inputStop );

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = ldtStart.atZone( z ); // Invalid values may be adjusted, such as during the hour of a "Spring-forward" Daylight Saving Time (DST) switch-over.
ZonedDateTime zdtStop = ldtStop.atZone( z );

Period p = Period.between ( zdtStart.toLocalDate () , zdtStop.toLocalDate () ).minusDays ( 1 ); // Subtract one, as we account for hours of first day.

// Get the Duration of first day's hours-minutes-seconds.
ZonedDateTime zdtStartNextDay = zdtStart.toLocalDate ().plusDays ( 1 ).atStartOfDay ( z );
Duration dStart = Duration.between ( zdtStart , zdtStartNextDay );

// Get the Duration of first day's hours-minutes-seconds.
ZonedDateTime zdtStopStartOfDay = zdtStop.toLocalDate ().atStartOfDay ( z );
Duration dStop = Duration.between ( zdtStopStartOfDay , zdtStop );

// Combine the pair of partial days into a single Duration.
Duration d = dStart.plus ( dStop );

System.out.println ( "zdtStart: " + zdtStart );
System.out.println ( "zdtStop: " + zdtStop );
System.out.println ( "p: " + p );
System.out.println ( "dStart: " + dStart + " and dStop: " + dStop );
System.out.println ( "d: " + d );

int years = p.getYears ();
int months = p.getMonths ();
int days = p.getDays ();
System.out.println( "Years: " + years + "\nMonths: " + months + "\nDays: " + days );

// Enable if in Java 9 or later (but not in Java 8)
// long durationDays = d.toDaysPart();
// long hours = d.toHoursPart();
// long minutes = d.toMinutesPart();
// long seconds = d.toSecondsPart();
// int nanos = d.toNanosPart();


提示: ThreeTen-Extra库提供了一个类 Interval来跟踪一对 Instant对象。 Instant是UTC时间轴上的时刻。您可以通过调用 InstantZonedDateTime中提取 toInstant



关于java.time

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

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

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

在哪里获取java.time类?


Java SE 8SE 9及更高版本


内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。

Java SE 6SE 7


ThreeTen-Backport中的大部分java.time功能都已反向移植到Java 6和7。

Android


ThreeTenABP项目专为Android改编了ThreeTen-Backport(如上所述)。
请参见 How to use ThreeTenABP…



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

关于java - 在Java中获取两个日期之间的精确差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41816893/

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