Java 中两个日期的求和
如何在 Java 中添加两个日期?
示例:“2010-01-14 19:16:17”“0000-10-03 01:10:05”的总和
将导致“2010-11-17 20:26:22”。
我知道如何使用日历并逐个字段添加字段来做到这一点。
还有其他方法可以一次将它们全部求和(年/月/日/小时/分钟/秒)吗?
How can I add two dates in 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".
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
如果您使用的是 Date 对象,您可以这样做:
代码使用
.getTime()
方法返回自纪元以来的毫秒数。不用说
Date
类有很多问题,应该尽可能避免。您想对其他类型求和吗?
更新:对于
Calendar
,我会执行以下操作(基于 javadocs):更新:正如 Steve 所说,如果您在此处提供的日期假设第二个日期是相对于 Java 纪元的,则此操作有效。如果您确实想从“0”年开始,那么您需要考虑到这一点(通过减去您的纪元时间)。
If you are using the Date object, you can just do:
The code uses the
.getTime()
method that returns the number of milliseconds since the epoch.Needless to say the
Date
class has a lot of problems and should be avoided when possible.Do you want to sum other types instead?
Update: for
Calendar
, I would do the following (based on javadocs):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).
不要将两个日期的时间以毫秒为单位相加!
只需克隆
Calendar
并一一添加日期时间部分即可。不用说,JodaTime 在此方面更加智能和干净。
Don't sum the time in millis of the two dates!
Just clone the
Calendar
and add the datetime parts one by one.Needless to say, JodaTime is smarter and cleaner with this.
一如既往,我会推荐 Java 8 日期/时间 API 或 Joda 进行日期/时间工作,因为它们更加更加强大和直观。
您可以将持续时间和周期添加到 DateTime 简单地反对。您可以同样轻松地添加分钟/秒/月。
但是,您不能直接添加两个日期,因为这实际上没有意义。这有力地说明了为什么 Joda 可以提供帮助——它可以阻止你做你不应该做的事情。
As always, I would recommend the Java 8 date/time APIs or Joda for date/time work, since they are much more powerful and intuitive.
You can add durations and periods to a DateTime object trivially. You can add minutes/seconds/months equally easily.
However, you can't add 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.
tl;dr
ISO 8601
使用与时刻相同的格式来表示时间跨度会造成混乱。跨度与时刻完全不同。
我建议使用标准的 ISO 8601 格式 PnYnMnDTnHnMnS。在此格式中,
P
标记开始(可能是“Period”),T
将年-月-日部分与时-分-秒部分分开。示例值:
PT1H30M
→ 一个半小时。P3Y6M4DT12H30M5S
→ 三年六个月零四天十二小时三十分钟零五秒。P10M3DT1H10M5S
→ 您的问题的持续时间为0000-10-03 01:10:05
。java.time
问题和其他答案使用麻烦的旧日期时间类,现在已经过时了 java.time 框架内置于 Java 8 及更高版本中。请参阅 Oracle 教程。许多 java.time 功能已向后移植到 Java 6 和 Java 6。 ThreeTen-Backport 中的 7 并在 ThreeTenABP。
在解析和生成表示日期时间值的字符串时,java.time 类默认使用 ISO 8601 格式。
该问题没有提供任何时区信息,因此这里我们使用
LocalDateTime
类。如果我们知道相对于 UTC 的偏移量,我们将使用 OffsetDateTime 类,如果我们知道时区,我们将使用 ZonedDateTime 类。java.time 中的时间跨度被划分为一对类。年-月-日由
表示period
类和小时-分钟-秒由持续时间
类。结合这些时间,我们确实可以执行日期时间数学运算。在这里,我们将一段时间添加到开始日期时间以获得结果日期时间。我们只需很少的代码行即可完成此操作。结果确实是提问者所期望的。
我们通过用
T
替换中间的空格,将输入字符串转换为规范的 ISO 8601 格式。与问题中预期的结果进行比较。
转储到控制台。
tl;dr
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-SS
format for a span of time, I suggest using the standard ISO 8601 format of PnYnMnDTnHnMnS. In this format, theP
marks the beginning (for "Period" presumably) and theT
separates the years-month-days portion from the hours-minutes-seconds portion.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 of0000-10-03 01:10:05
.java.time
The Question and the other Answers use troublesome old date-time classes now outmoded by the java.time framework 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-Backport and further adapted to Android in ThreeTenABP.
The java.time classes use ISO 8601 formats by default when parsing and generating Strings that represent date-time values.
The Question does not provide any time zone info, so here we use the
LocalDateTime
class. If we know an offset-from-UTC we would use theOffsetDateTime
class, and if even better we knew a time zone, we would use theZonedDateTime
class.Spans of time in java.time are divided amongst a pair of classes. Years-months-days are represented by the
Period
class, and hours-minutes-seconds are handled by theDuration
class.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
.Compare to the result expected in the Question.
Dump to console.
您希望对这两个日历执行
getTimeInMillis()
操作,这样您就可以将两个诚实的long
值相加。然后,您可以使用该日历的setTimeInMillis()
方法获取总和并将其存储在新日历中。当然,是否要添加如上所示的两个
Calendar
或如 notnoop 的答案中所示的两个Date
取决于您。效果类似,只是取决于你想对结果做什么。Date
主要用于存储和/或转换为字符串以供打印或显示,而Calendar
则可以让您随意调整各个时间值(如果您愿意的话)选择。正如其他人提到的,您在使用
Date
或Calendar
时犯了一些概念上的禁忌,它们旨在存储“真实”日期和时间,例如20世纪或21世纪,作为间隔,即时间跨度。标准 Java 库中的类没有为您提供真正有用的工具来处理此问题,这就是开发 Joda 类的原因。所有日期/时间处理中的酷孩子都使用它们;但另一方面,这涉及下载和管理第三方库。You want to do
getTimeInMillis()
on both those Calendars so you'll have two honest-to-goodnesslong
values you can add up. You can then take the sum and stash it in a new Calendar using that Calendar'ssetTimeInMillis()
method.Whether you want to add two
Calendar
s as shown above or twoDate
s 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. ADate
is mostly just good for storing and/or converting to a String for printing out or displaying, whereas aCalendar
will let you fiddle with the individual time values should you so choose.As others have mentioned, you're committing some conceptual no-no's in using a
Date
orCalendar
, 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.notnoop 的答案绝对是正确的。但是,如果您要对日期、时间和间隔进行大量处理,我建议您查看 apache commons lang 和 joda-time 库。
JDK7 将为 joda-time 提供的一些功能提供更好的支持。只是说......如果您的应用程序大量使用这些东西,这可能是一个考虑因素。
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 lang and at joda-time library.
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.
您需要定义您的 EPOCH。 Java 纪元(与 Unix 一样)是 1970 年 1 月 1 日 GMT/UTC。我假设您认为您从 0000 年 1 月 1 日起添加了 10 个月、3 天和一些奇怪的时间,但您的纪元偏移量一直到 1970 年。数学可能不一定有效。
使用 Calendar 或 Joda(如上所述)。如果您只是想添加秒数和天数 (&c),那么请随意将所述毫秒数添加到您的第一个日期对象中。
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.
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.
在java中使用日历类add方法添加两个日期。
通过使用 Calendar 类中的 add 方法,我们可以向现有日期添加日、月、年。
单击此处查看完整程序。
Use calendar class add method to add two dates in java.
By using add method in Calendar class we can add day,month,year to the existing date.
click here for complete program.
我偶尔也会犯这种做法,将时间间隔存储在日期对象中并按照 notnoop 的建议使用 getTime() 。
有用。与某些观点相反,它确实有效。我只是忽略了该间隔可能代表意外的日期。对我来说,向日期添加间隔(例如 [6 年、6 个月、6 天、6 小时、6 分钟、6 秒])是一种快速而肮脏的方法。
I am occasionally guilty of this practice too, storing time interval in a date object and using getTime() as suggested by notnoop.
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.