用Java总结两个日期

时间:2010-01-14 21:21:42

标签: java date calendar

如何在Java中添加两个日期?

示例:“2010-01-14 19:16:17”“0000-10-03 01:10:05”的总和 会导致“2010-11-17 20:26:22”。

我知道如何使用日历并按字段添加字段。

是否可以通过其他方式将所有这些(年/月/日/小时/分钟/秒)加起来?

9 个答案:

答案 0 :(得分:28)

如果您使用的是Date对象,则可以执行以下操作:

Date d1 = ...
Date d2 = ...

long sum = d1.getTime() + d2.getTime();

Date sumDate = new Date(sum);

代码使用.getTime()方法返回自纪元以来的毫秒数。 毋庸置疑,Date类存在很多问题,应尽可能避免使用。

您想要将其他类型相加吗?

更新:对于Calendar,我会执行以下操作(基于javadocs):

Calendar c1 = ...
Calendar c2 = ...
long sum = c1.getTimeInMillis() + c2.getTimeInMillis();
Calendar sumCalendar = (Calendar)c1.clone();
sumCalendar.setTimeInMillis(sum);

更新:正如史蒂夫所说,如果您在此处提供的日期假定第二个日期与Java时期相关,则此方法有效。如果你想以年份“0”开头,那么你需要考虑到这一点(通过减去你的纪元时间)。

答案 1 :(得分:9)

与往常一样,我建议Joda用于日期/时间工作,因为它很多更强大和直观。

您可以轻松地将持续时间和句点添加到DateTime对象。您可以轻松地添加分钟/秒/月。

但是,你不能直接添加两个日期,因为这没有多大意义。这是为什么Joda是一个帮助的有力例证 - 它阻止你做你真正不应该做的事情。

答案 2 :(得分:9)

不要将两个日期的毫秒时间相加!

Date d1 = new Date();
Date d2 = new Date();
Date dTotal = new Date(d1.getTime() + d2.getTime());
System.out.println(dTotal); // Incorrect! Misses about 1970 years.

只需克隆Calendar并逐个添加日期时间部分。

Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
Calendar cTotal = (Calendar) c1.clone();
cTotal.add(Calendar.YEAR, c2.get(Calendar.YEAR));
cTotal.add(Calendar.MONTH, c2.get(Calendar.MONTH) + 1); // Months are zero-based!
cTotal.add(Calendar.DATE, c2.get(Calendar.DATE));
cTotal.add(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY));
cTotal.add(Calendar.MINUTE, c2.get(Calendar.MINUTE));
cTotal.add(Calendar.SECOND, c2.get(Calendar.SECOND));
cTotal.add(Calendar.MILLISECOND, c2.get(Calendar.MILLISECOND));
System.out.println(cTotal.getTime()); // Correct!

毋庸置疑,JodaTime更聪明,更清洁。

答案 3 :(得分:5)

TL;博士

LocalDateTime later = 
    LocalDateTime
    .parse ( 
        "2010-01-14 19:16:17"
        .replace ( " " , "T" ) 
    )
    .plus( Period.parse ( "P10M3D" ) )
    .plus( Duration.parse ( "PT1H10M5S" ) ) 
;

ISO 8601

使用相同格式表示时间跨度会造成混淆。跨度与片刻完全不同。

我建议使用标准的ISO 8601格式PnYnMnDTnHnMnS,而不是在一段时间内使用YYYY-MM-DD HH-MM-SS格式。在这种格式中,P标记开头(可能是“期间”),T将年 - 月 - 日部分与小时 - 分 - 秒部分分开。

示例值:

  • PT1H30M→一个半小时。
  • P3Y6M4DT12H30M5S→三年,六个月,四天,十二小时,三十五分五秒。
  • P10M3DT1H10M5S→您的问题的持续时间为0000-10-03 01:10:05

java.time

问题和其他答案使用了麻烦的旧日期时间类,现在已经过时了Java 8及更高版本中内置的java.time框架。见Oracle Tutorial。许多java.time功能已经被反向移植到Java 6& ThreeTen-Backport中的7,并在ThreeTenABP中进一步适应Android。

在解析和生成表示日期时间值的字符串时,java.time类默认使用ISO 8601格式。

该课题不提供任何时区信息,因此我们在这里使用LocalDateTime课程。如果我们知道从UTC的偏移量,我们将使用OffsetDateTime类,如果我们知道时区更好,我们将使用ZonedDateTime类。

java.time中的时间跨度分为一对类。年 - 月 - 天由Period类表示,小时 - 分钟 - 秒由Duration类处理。

结合这些时间,我们确实可以执行日期时间数学运算。在这里,我们将一段时间添加到开始日期时间以获得结果日期时间。我们只用很少的代码就行了。结果确实是该问题的预期结果。

我们将输入字符串转换为规范的ISO 8601格式,将中间的空格替换为T

LocalDateTime ldt = LocalDateTime.parse ( "2010-01-14 19:16:17".replace ( " " , "T" ) );
//"0000-10-03 01:10:05"
Period period = Period.parse ( "P10M3D" );
Duration duration = Duration.parse ( "PT1H10M5S" );
LocalDateTime result = ldt.plus ( period ).plus ( duration );

与问题中预期的结果相比较。

LocalDateTime expectation = LocalDateTime.parse ( "2010-11-17 20:26:22".replace ( " " , "T" ) );
Boolean isSame = result.equals ( expectation );

转储到控制台。

System.out.println ( "ldt: " + ldt + " + period: " + period + " + duration: " + duration + " is result: " + result + " compared to expectation: " + expectation + " is the same: " + isSame );
  

ldt:2010-01-14T19:16:17 +期间:P10M3D +持续时间:PT1H10M5S结果:2010-11-17T20:26:22与预期相比:2010-11-17T20:26:22是一样的:真的

答案 4 :(得分:3)

您希望在这两个日历上都getTimeInMillis(),因此您可以添加两个诚实至善long的值。然后,您可以使用该日历的setTimeInMillis()方法获取总和并将其存储在新日历中。

当你想要添加两个Calendar如上所示或两个Date时,如notnoop的答案所示,由你自己决定。效果类似,它只取决于你想对结果做什么。 Date主要用于存储和/或转换为字符串以便打印或显示,而Calendar则可以让您根据个人时间值进行操作。

正如其他人所提到的那样,你在使用DateCalendar时会犯一些概念上的禁忌,这意味着存储“真实”的日期和时间,例如在20世纪或21世纪,作为间隔,即时间跨度。标准Java库中的类没有为您提供真正有用的工具来处理这个问题,这就是为什么开发Joda类的原因。所有在日期/时间处理中的酷孩子都使用这些;但另一方面涉及下载和管理第三方库。

答案 5 :(得分:2)

notnoop回答绝对是正确的。但是,如果您要对日期,时间和间隔进行大量处理,我建议您查看apache commons langjoda-time库中的DateUtils类。

JDK7将更好地支持joda-time提供的一些功能。只是说......如果你的应用程序大量使用这些东西,可能需要考虑。

答案 6 :(得分:1)

您需要定义EPOCH。 Java时代(如Unix)是1970年1月1日GMT / UTC。我假设你认为你从0000年1月1日开始增加十个月,三天和一些奇数小时但你有一个时期偏移到1970年。数学可能不一定有用。

使用Calendar或Joda(如上所述)。如果您只是想添加一些秒和天(& c),那么可以随意将所述的毫秒数添加到您的第一个日期对象中。

答案 7 :(得分:0)

使用日历类添加方法在java中添加两个日期。

Calendar calendar=Calendar.getInstance();

calendar.add(Calendar.Date,23);

calendar.add(Calendar.Month,13);

calendar.add(Calendar.Year,15);

通过在Calendar类中使用add方法,我们可以将日,月,年添加到现有日期。

click here for complete program.

答案 8 :(得分:-1)

我偶尔也会犯这种做法,将时间间隔存储在日期对象中,并按照notnoop的建议使用getTime()。

有效。与某些观点相反,它肯定有效。我只是忽略了间隔可以代表一个非预期的日期。对于我来说,这是一种快速而又肮脏的方式,例如,[6年,6个月,6天,6小时,6分钟,6秒]添加间隔。