Java 中的两个日期相加

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2067657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:11:47  来源:igfitidea点击:

Sum two dates in Java

javadatecalendar

提问by Diego Dias

How can I add two dates in Java?

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

Example: The sum of "2010-01-14 19:16:17" "0000-10-03 01:10:05"
would result in "2010-11-17 20:26:22".

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

I know how to do it using Calendar and adding field by field.

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

Is any other way to sum them all (year/month/day/hour/minute/second) at once?

有没有其他方法可以一次将它们全部相加(年/月/日/小时/分钟/秒)?

采纳答案by notnoop

If you are using the Date object, you can just do:

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

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

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

Date sumDate = new Date(sum);

The code uses the .getTime()method that returns the number of milliseconds since the epoch. Needless to say the Dateclass has a lot of problems and should be avoided when possible.

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

Do you want to sum other types instead?

你想对其他类型求和吗?

Update: for Calendar, I would do the following (based on javadocs):

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

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

UPDATED: As Steve stated, this works if the Date you presented here assumes that the second date is with respect to the Java epoch. If you do want to start with year "0", then you need to account for that (by subtracting your epoch time).

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

回答by Brian Agnew

As always, I would recommend the Java 8 date/time APIs or Jodafor date/time work, since they are muchmore powerful and intuitive.

与往常一样,我会建议在Java 8日期/时间API或乔达日期/时间的工作,因为他们有很多更强大,更直观。

You can add durations and periods to a DateTimeobject trivially. You can add minutes/seconds/months equally easily.

您可以轻松地向DateTime对象添加持续时间和时间段。您可以同样轻松地添加分钟/秒/月。

However, you can'tadd two dates directly, since that doesn't really make sense. This is a powerful illustration of why Joda is a help - it stops you doing stuff that you really shouldn't be doing.

但是,您不能直接添加两个日期,因为这没有任何意义。这有力地说明了为什么 Joda 是一种帮助——它阻止你做你真正不应该做的事情。

回答by Carl Smotricz

You want to do getTimeInMillis()on both those Calendars so you'll have two honest-to-goodness longvalues you can add up. You can then take the sum and stash it in a new Calendar using that Calendar's setTimeInMillis()method.

您想getTimeInMillis()在这两个日历上都这样做,这样您就可以将两个诚实至善的long价值观相加。然后,您可以使用该日历的setTimeInMillis()方法获取总和并将其存储在新日历中。

Whether you want to add two Calendars as shown above or two Dates as shown in notnoop's answer is up to you, of course. The effect is similar, it just depends on what you want to do with the result. A Dateis mostly just good for storing and/or converting to a String for printing out or displaying, whereas a Calendarwill let you fiddle with the individual time values should you so choose.

当然,您是要添加Calendar如上所示的两个Dates 还是如 notnoop 的答案中所示的两个s 取决于您。效果是相似的,这只是取决于你想对结果做什么。ADate主要用于存储和/或转换为用于打印或显示的字符串,而如果Calendar您愿意,a将让您摆弄各个时间值。

As others have mentioned, you're committing some conceptual no-no's in using a Dateor Calendar, which are meant to store "real" dates and times, e.g. ones in the 20th or 21st century, as intervals, i.e. time spans. The classes in the standard Java library don't give you really useful tools to handle this, which is why the Joda classes were developed. All the cool kids in date/time processing use those; but on the other hand that involves downloading and managing a 3rd party library.

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

回答by Yoni

notnoop answer is definitely correct. However, if you are going to do lots of processing of dates, times and intervals, I suggest that you look at class DateUtils in apache commons langand at joda-timelibrary.

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

JDK7 will come with better support for some of the features that joda-time provides. Just saying ... it might be a consideration if your app makes heavy usage of this stuff.

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

回答by Jé Queue

You need to define your EPOCH. The Java epoch (like Unix) is 1 Jan 1970 GMT/UTC. I assume you think you're adding ten months, 3 days and some odd hours from 1 Jan 0000 but you have a epoch offset until 1970. The maths may not necessarily work.

您需要定义您的 EPOCH。Java 纪元(如 Unix)是 1970 年 1 月 1 日 GMT/UTC。我假设您认为您从 0000 年 1 月 1 日开始增加了 10 个月、3 天和一些奇数小时,但您在 1970 年之前有一个纪元偏移量。数学可能不一定有效。

Use Calendar or Joda (as mentioned). If you just simply want to add a number of seconds and days (&c) then feel free to add said # of milliseconds to your first date object.

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

回答by Blessed Geek

I am occasionally guilty of this practice too, storing time interval in a date object and using getTime() as suggested by notnoop.

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

It works. Contrary to certain opinion, it certainly works. I just ignore that the interval could be representative of an unintended date. It is a quick and dirty way for me to add an interval, say, [6 years, 6 months, 6 days, 6 hours, 6 minutes, 6 seconds] to a date.

有用。与某些观点相反,它确实有效。我只是忽略了间隔可能代表意外日期。对我来说,这是一种快速而肮脏的方法,可以为日期添加一个间隔,例如 [6 年、6 个月、6 天、6 小时、6 分钟、6 秒]。

回答by BalusC

Don't sum the time in millis of the two dates!

不要将两个日期的时间相加,以毫秒为单位!

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.

Just clone the Calendarand add the datetime parts one by one.

只需克隆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!

Needless to say, JodaTime is smarter and cleaner with this.

不用说,JodaTime 在这方面更智能、更干净。

回答by user2822053

Use calendar class add method to add two dates in java.

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

Calendar calendar=Calendar.getInstance();

calendar.add(Calendar.Date,23);

calendar.add(Calendar.Month,13);

calendar.add(Calendar.Year,15);

By using add method in Calendar class we can add day,month,year to the existing date.

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

click here for complete program.

单击此处获取完整程序。

回答by Basil Bourque

tl;dr

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

The representation of a span-of-time using the same format as a moment is creating confusion. A span is not at all the same as a moment.

使用与时刻相同的格式来表示时间跨度正在造成混乱。跨度与片刻完全不同。

Instead of using YYYY-MM-DD HH-MM-SSformat for a span of time, I suggest using the standard ISO 8601format of PnYnMnDTnHnMnS. In this format, the Pmarks the beginning (for "Period" presumably) and the Tseparates the years-month-days portion from the hours-minutes-seconds portion.

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

Example values:

示例值:

  • PT1H30M→ One and a half hours.
  • P3Y6M4DT12H30M5S→ Three years, six months, four days, twelve hours, thirty minutes, and five seconds.
  • P10M3DT1H10M5S→ Your Question's duration of 0000-10-03 01:10:05.
  • PT1H30M→ 一个半小时。
  • P3Y6M4DT12H30M5S→ 三年六个月四天十二小时三十分五秒。
  • P10M3DT1H10M5S→ 您的问题的持续时间为0000-10-03 01:10:05

java.time

时间

The Question and the other Answers use troublesome old date-time classes now outmoded by the java.timeframework built into Java 8 and later. See Oracle Tutorial. Much of the java.time functionality has been back-ported to Java 6 & 7 in ThreeTen-Backportand further adapted to Android in ThreeTenABP.

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

The java.time classes use ISO 8601 formats by default when parsing and generating Strings that represent date-time values.

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

The Question does not provide any time zone info, so here we use the LocalDateTimeclass. If we know an offset-from-UTC we would use the OffsetDateTimeclass, and if even better we knew a time zone, we would use the ZonedDateTimeclass.

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

Spans of time in java.time are divided amongst a pair of classes. Years-months-days are represented by the Periodclass, and hours-minutes-seconds are handled by the Durationclass.

java.time 中的时间跨度被分成一对类。年-月-日由Period类表示,时-分-秒由Duration类处理。

Combining these times, we can indeed perform date-time math. Here we add a span of time to an starting date-time to get a resulting date-time. And we do so in very few lines of code. The result is indeed that expected by the Question.

结合这些时间,我们确实可以执行日期时间数学。在这里,我们将时间跨度添加到起始日期时间以获得结果日期时间。我们只用很少的代码行就可以做到这一点。结果确实是问题所预期的。

We convert the input strings to canonical ISO 8601 format by replacing the SPACE in the middle with a T.

我们将输入字符串转换为规范的 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 );

Compare to the result expected in the Question.

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

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

Dump to console.

转储到控制台。

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 + period: P10M3D + duration: PT1H10M5S is result: 2010-11-17T20:26:22 compared to expectation: 2010-11-17T20:26:22 is the same: true

ldt: 2010-01-14T19:16:17 + period: P10M3D + duration: PT1H10M5S 结果:2010-11-17T20:26:22 与预期相比:2010-11-17T20:26:22 是一样的:tr​​ue