如何在Java中添加两个日期?
示例:“2010-01-14 19:16:17”“0000-10-03 01:10:05”的总和 会导致“2010-11-17 20:26:22”。
我知道如何使用日历并按字段添加字段。
是否可以通过其他方式将所有这些(年/月/日/小时/分钟/秒)加起来?
答案 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)
LocalDateTime later =
LocalDateTime
.parse (
"2010-01-14 19:16:17"
.replace ( " " , "T" )
)
.plus( Period.parse ( "P10M3D" ) )
.plus( Duration.parse ( "PT1H10M5S" ) )
;
使用相同格式表示时间跨度会造成混淆。跨度与片刻完全不同。
我建议使用标准的ISO 8601格式PnYnMnDTnHnMnS,而不是在一段时间内使用YYYY-MM-DD HH-MM-SS
格式。在这种格式中,P
标记开头(可能是“期间”),T
将年 - 月 - 日部分与小时 - 分 - 秒部分分开。
示例值:
PT1H30M
→一个半小时。P3Y6M4DT12H30M5S
→三年,六个月,四天,十二小时,三十五分五秒。P10M3DT1H10M5S
→您的问题的持续时间为0000-10-03 01:10:05
。问题和其他答案使用了麻烦的旧日期时间类,现在已经过时了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
则可以让您根据个人时间值进行操作。
正如其他人所提到的那样,你在使用Date
或Calendar
时会犯一些概念上的禁忌,这意味着存储“真实”的日期和时间,例如在20世纪或21世纪,作为间隔,即时间跨度。标准Java库中的类没有为您提供真正有用的工具来处理这个问题,这就是为什么开发Joda类的原因。所有在日期/时间处理中的酷孩子都使用这些;但另一方面涉及下载和管理第三方库。
答案 5 :(得分:2)
notnoop回答绝对是正确的。但是,如果您要对日期,时间和间隔进行大量处理,我建议您查看apache commons lang和joda-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方法,我们可以将日,月,年添加到现有日期。
答案 8 :(得分:-1)
我偶尔也会犯这种做法,将时间间隔存储在日期对象中,并按照notnoop的建议使用getTime()。
有效。与某些观点相反,它肯定有效。我只是忽略了间隔可以代表一个非预期的日期。对于我来说,这是一种快速而又肮脏的方式,例如,[6年,6个月,6天,6小时,6分钟,6秒]添加间隔。