用Java总结两个日期

Die*_*ias 15 java calendar date

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

示例:"2010-01-14 19:16:17""0000-10-03 01:10:05"的总和
将导致"2010-11-17 20:26:22".

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

有没有其他方法可以一次性总结它们(年/月/日/小时/分钟/秒)?

not*_*oop 27

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

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

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

Date sumDate = new Date(sum);
Run Code Online (Sandbox Code Playgroud)

代码使用.getTime()返回自纪元以来毫秒数的方法.不用说,Date课程有很多问题,应尽可能避免.

你想要总结其他类型吗?

更新:for Calendar,我会做以下(基于javadocs):

Calendar c1 = ...
Calendar c2 = ...
long sum = c1.getTimeInMillis() + c2.getTimeInMillis();
Calendar sumCalendar = (Calendar)c1.clone();
sumCalendar.setTimeInMillis(sum);
Run Code Online (Sandbox Code Playgroud)

更新:正如史蒂夫所说,如果你在这里提出的日期假设第​​二个日期是关于Java时期的,那么这是有效的.如果你想以年份"0"开头,那么你需要考虑到这一点(通过减去你的纪元时间).

  • 这是不正确的.Java的时代是1970年.所以使用Date来表示一个持续时间(例如一分钟00:01这样的函数)是行不通的.试试看吧. (8认同)
  • 示例:1970-00-00 00:00 = 0毫秒,因此使用您的算法将1970-00-00 00:00添加到1970-00-00 00:00产生1970-00-00 00:00,其中作为OP预计它是3940-00-00 00:00. (2认同)

Bri*_*new 10

与往常一样,我会建议乔达日期/时间的工作,因为它是很多更强大,更直观.

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

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


Bal*_*usC 10

不要总结这两个日期的毫秒时间!

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.
Run Code Online (Sandbox Code Playgroud)

只需克隆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!
Run Code Online (Sandbox Code Playgroud)

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


Bas*_*que 5

TL;博士

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

ISO 8601

使用与片刻相同的格式表示时间跨度会产生混淆.跨度与片刻完全不同.

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

示例值:

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

java.time

问题和其他答案使用了麻烦的旧日期时间类,现在已经过时了Java 8及更高版本中内置的java.time框架.请参阅Oracle教程.多的java.time功能已被后移植到Java 6和7在ThreeTen-反向移植并且还适于在到Android ThreeTenABP.

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

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

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

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

我们将输入字符串转换为规范的ISO 8601格式,将中间的空格替换为a 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 );
Run Code Online (Sandbox Code Playgroud)

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

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

转储到控制台.

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

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