我正在寻找一种方法来获取两个日期之间的差异,正如标题所说,用Java。例如,如果d1 = 2017-01-23 05:25:00
和d2 = 2018-03-20 07:29:50
,则会打印一些方法
Years: 1
Months: 1
Days: 25
Hours: 2
Minutes: 4
Seconds: 50
我曾尝试使用LocalDateTime对象执行此操作,但我找不到一种方法来获取它们之间的月份。我认为不需要包含该代码,但如果需要,我可以。我不关心日期是什么类型,但我不想使用Joda时间或其他外部库。提前感谢您的帮助。
答案 0 :(得分:3)
我们必须解析你的字符串。在解析/生成字符串时,java.time类在默认情况下使用标准ISO 8601格式。您的投入接近遵守;我们只需要用T
替换中间的SPACE。
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 );
Period
& Duration
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 );
转储到控制台。 toString
&上的Period
方法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
开始: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时间轴上的时刻。您可以通过调用ZonedDateTime
从toInstant
中提取Instant
。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 1 :(得分:-1)
package com.mkyong.date;
import java.text.SimpleDateFormat; import java.util.Date;
public class DateDifferentExample {
public static void main(String[] args) {
String dateStart = "01/14/2012 09:29:58";
String dateStop = "01/15/2012 10:31:48";
//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
java.util.Date d1 = null;
java.util.Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
//in milliseconds
long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果
1天,1小时,1分钟,50秒。
答案 2 :(得分:-1)
我会把你想要的两个日期和时间放到SimpleDateFormat中。然后你可以只做date.getTime()并以毫秒为单位返回距离,然后可以将其转换回几天,几年或几个月。这是我写的一个例子:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.ParseException;
public class DateTest{
public static void main(String[] args) throws ParseException{
System.out.println("Current time in milliseconds: " + System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss MM/dd/yyyy");
String dateAndTime1 = "2:30:00 1/23/2017";
String dateAndTime2 = "1:45:00 5/23/2015";
Date date1 = format.parse(dateAndTime1);
Date date2 = format.parse(dateAndTime2);
long difference = date1.getTime() - date2.getTime();
System.out.println("The difference in milliseconds is " + difference);
}
}