计算两个 Java 日期实例之间的差异
我在 Scala 中使用 Java 的 java.util.Date
类,并且想要比较 Date
对象和当前时间。我知道我可以使用 getTime() 来计算增量:
(new java.util.Date()).getTime() - oldDate.getTime()
但是,这只会给我留下一个代表毫秒的 long
。有没有更简单、更好的方法来获取时间增量?
I'm using Java's java.util.Date
class in Scala and want to compare a Date
object and the current time. I know I can calculate the delta by using getTime():
(new java.util.Date()).getTime() - oldDate.getTime()
However, this just leaves me with a long
representing milliseconds. Is there any simpler, nicer way to get a time delta?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
简单的 diff (不带 lib)
然后你可以调用:
来获取 2 个日期的差异(以分钟为单位)。
TimeUnit
是java.util.concurrent.TimeUnit
,一个从纳秒到天的标准 Java 枚举。人类可读的差异(不带 lib)
http://ideone.com/5dXeu6
输出类似于
Map :{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
,单位已排序。您只需将该映射转换为用户友好的字符串即可。
警告
上面的代码片段计算两个时刻之间的简单差异。它可能会在夏令时切换期间导致问题,如这篇文章中所述。这意味着,如果您计算没有时间的日期之间的差异,则可能会缺少日期/小时。
在我看来,日期差异有点主观,尤其是在几天内。您可以:
计算 24 小时经过的时间:天+1 - 天=1 天=24 小时
计算经过的时间数,考虑夏令时:day+1 - day = 1 = 24h(但使用午夜时间和夏令时)节省时间可能是 0 天 23 小时)
计算
日切换的数量
,这意味着 day+1 1pm - day 11am = 1 天,即使经过的时间只有 2 小时(如果有夏令时则为 1 小时:p)我的答案是如果您对天数的日期差异的定义与第一种情况匹配,则有效 使用
JodaTime
如果您使用 JodaTime,您可以通过以下方式获取 2 个瞬间(米莉支持 ReadableInstant)日期的差异:
但您也可以获取本地日期/时间的差异:
Simple diff (without lib)
And then you can call:
to get the diff of the 2 dates in minutes unit.
TimeUnit
isjava.util.concurrent.TimeUnit
, a standard Java enum going from nanos to days.Human readable diff (without lib)
http://ideone.com/5dXeu6
The output is something like
Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
, with the units ordered.You just have to convert that map to a user-friendly string.
Warning
The above code snippets compute a simple diff between 2 instants. It can cause problems during a daylight saving switch, like explained in this post. This means if you compute the diff between dates with no time you may have a missing day/hour.
In my opinion the date diff is kind of subjective, especially on days. You may:
count the number of 24h elapsed time: day+1 - day = 1 day = 24h
count the number of elapsed time, taking care of daylight savings: day+1 - day = 1 = 24h (but using midnight time and daylight savings it could be 0 day and 23h)
count the number of
day switches
, which means day+1 1pm - day 11am = 1 day, even if the elapsed time is just 2h (or 1h if there is a daylight saving :p)My answer is valid if your definition of date diff on days match the 1st case
With JodaTime
If you are using JodaTime you can get the diff for 2 instants (millies backed ReadableInstant) dates with:
But you can also get the diff for Local dates/times:
不幸的是,JDK
Date
API 严重损坏。我建议使用 Joda Time 库。Joda Time 有一个时间概念 间隔:
编辑:顺便说一下,Joda 有两个概念:
Interval
用于表示两个时刻之间的时间间隔(表示上午 8 点到 10 点之间的时间),以及Duration
表示没有实际时间的时间长度边界(例如代表两个小时!)如果您只关心时间比较,大多数
Date
实现(包括 JDK 的)都实现Comparable
接口,该接口允许您使用Comparable.compareTo()
The JDK
Date
API is horribly broken unfortunately. I recommend using Joda Time library.Joda Time has a concept of time Interval:
EDIT: By the way, Joda has two concepts:
Interval
for representing an interval of time between two time instants (represent time between 8am and 10am), and aDuration
that represents a length of time without the actual time boundaries (e.g. represent two hours!)If you only care about time comparisions, most
Date
implementations (including the JDK one) implementsComparable
interface which allows you to use theComparable.compareTo()
请注意,这适用于 UTC 日期,因此如果您查看本地日期,差异可能是休息一天。由于夏令时的原因,要使其与本地日期正确配合需要采用完全不同的方法。
Note that this works with UTC dates, so the difference may be a day off if you look at local dates. And getting it to work correctly with local dates requires a completely different approach due to daylight savings time.
使用 java.time 框架构建进入 Java 8+:
输出:
有关详细信息,请参阅 Oracle 教程 和 ISO 8601 标准。
Using the java.time framework built into Java 8+:
Output:
For more info, see the Oracle Tutorial and the ISO 8601 standard.
tl;dr
将过时的
java.util.Date
对象转换为其替换对象java.time.Instant
。然后将经过的时间计算为Duration
。ISO 8601 格式:
PnYnMnDTnHnMnS
合理的标准 ISO 8601 定义了一段时间跨度的简明文本表示,如年、月、日、小时等。该标准将这样的跨度称为 < a href="https://en.wikipedia.org/wiki/ISO_8601#Durations" rel="noreferrer">持续时间。格式为
PnYnMnDTnHnMnS
,其中P
表示“周期”,T
将日期部分与时间部分分开,其间是后面跟随的数字通过一封信。示例:
P3Y6M4DT12H30M5S
三年六个月四天十二小时三十分钟五秒
PT4H30M
四个半小时
java.time
内置的 java.time 框架Java 8 及更高版本取代了麻烦的旧
java.util.Date
/java.util.Calendar
类。新类的灵感来自于非常成功的 Joda-Time 框架,旨在作为其后继者,类似在概念上但重新架构。由 JSR 310 定义。由 ThreeTen-Extra 项目扩展。请参阅教程。a
即时
类代表 UTC 时间轴上的一个时刻,分辨率为 纳秒(最多九 (9) 位小数)。最好避免使用遗留类,例如
Date
/Calendar
。但是,如果您必须与尚未更新到 java.time 的旧代码进行互操作,请来回转换。调用添加到旧类中的新转换方法。用于从java.util.Date< /code>
到
Instant
,调用日期::toInstant
。时间跨度
将这种将时间跨度表示为年、月、日、小时、分钟、秒的想法分成两半:
Period
代表年、月、日Duration
表示天、小时、分钟、秒这里就是一个例子。
转储到控制台。
Period
和Duration
均使用 ISO 8601< /a> 用于生成其值的字符串表示形式的标准。Java 9 向
Duration
获取天部分、小时部分、分钟部分和秒部分。您可以获得整个 Duration 内的总天数或小时数或分钟数或秒数或毫秒数或纳秒数。
在 Java 9 中,
Duration
类获得新方法返回天、小时、分钟、秒、毫秒/纳秒的各个部分。调用to...Part
方法:toDaysPart()
、toHoursPart()
等。ChronoUnit
如果您只关心更简单的较大时间粒度,例如“经过的天数”,请使用
ChronoUnit
枚举。另一个例子。
关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如
java.util.Date
,日历
,&SimpleDateFormat
。Joda-Time 项目,现位于 维护模式,建议迁移到 java.time。
要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310。
从哪里获取 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如
Interval
,YearWeek
,YearQuarter
,以及更多。Joda-Time
更新: Joda-Time 项目现已位于 维护模式,团队建议迁移到 java.time 类。我将这一部分原封不动地留作历史。
Joda-Time 库使用 ISO 8601 作为默认值。它的Period类解析并生成这些PnYnMnDTnHnMnS字符串。
渲染:
tl;dr
Convert your obsolete
java.util.Date
objects to their replacement,java.time.Instant
. Then calculate the elapsed time as aDuration
.ISO 8601 Format:
PnYnMnDTnHnMnS
The sensible standard ISO 8601 defines a concise textual representation of a span of time as a number of years, months, days, hours, etc. The standard calls such such a span a duration. The format is
PnYnMnDTnHnMnS
where theP
means "Period", theT
separates the date portion from the time portion, and in between are numbers followed by a letter.Examples:
P3Y6M4DT12H30M5S
three years, six months, four days, twelve hours, thirty minutes, and five seconds
PT4H30M
Four and a half hours
java.time
The java.time framework built into Java 8 and later supplants the troublesome old
java.util.Date
/java.util.Calendar
classes. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.Moment
The
Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).Best to avoid the legacy classes such as
Date
/Calendar
. But if you must inter-operate with old code not yet updated to java.time, convert back and forth. Call new conversion methods added to the old classes. For moving from ajava.util.Date
to anInstant
, callDate::toInstant
.Span of time
The java.time classes have split this idea of representing a span of time as a number of years, months, days, hours, minutes, seconds into two halves:
Period
for years, months, daysDuration
for days, hours, minutes, secondsHere is an example.
Dump to console.
Both
Period
andDuration
use the ISO 8601 standard for generating a String representation of their value.Java 9 adds methods to
Duration
to get the days part, hours part, minutes part, and seconds part.You can get the total number of days or hours or minutes or seconds or milliseconds or nanoseconds in the entire Duration.
In Java 9 the
Duration
class gets new methods for returning the various parts of days, hours, minutes, seconds, milliseconds/nanoseconds. Call theto…Part
methods:toDaysPart()
,toHoursPart()
, and so on.ChronoUnit
If you only care about a simpler larger granularity of time, such as “number of days elapsed”, use the
ChronoUnit
enum.Another example.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
,Calendar
, &SimpleDateFormat
.The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as
Interval
,YearWeek
,YearQuarter
, and more.Joda-Time
UPDATE: The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. I leave this section intact for history.
The Joda-Time library uses ISO 8601 for its defaults. Its
Period
class parses and generates these PnYnMnDTnHnMnS strings.Renders:
您需要更清楚地定义您的问题。例如,您可以仅获取两个
Date
对象之间的毫秒数,然后除以 24 小时内的毫秒数...但是:日期
始终采用 UTCYou need to define your problem more clearly. You could just take the number of milliseconds between the two
Date
objects and divide by the number of milliseconds in 24 hours, for example... but:Date
is always in UTChttps://www.joda.org/joda-time/faq.html#datediff
https://www.joda.org/joda-time/faq.html#datediff
由于这里的所有答案都是正确的,但使用遗留的java或第3方库,如joda或类似的库,我将使用新的 java.time 类。请参阅 Oracle 教程。
使用
LocalDate
和ChronoUnit
:Since all the answers here are correct but use legacy java or 3rd party libs like joda or similar, I will just drop another way using new java.time classes in Java 8 and later. See Oracle Tutorial.
Use
LocalDate
andChronoUnit
:一个稍微简单的替代方案:
至于“更好”:那么,您到底需要什么?将持续时间表示为小时数和天数等的问题在于,由于日期的复杂性,它可能会导致不准确和错误的期望(例如,由于夏令时,天可能有 23 或 25 小时)。
A slightly simpler alternative:
As for "nicer": well, what exactly do you need? The problem with representing time durations as a number of hours and days etc. is that it may lead to inaccuracies and wrong expectations due to the complexity of dates (e.g. days can have 23 or 25 hours due to daylight savings time).
使用毫秒方法可能会在某些区域设置中导致问题。
例如,两个日期 03/24/2007 和 03/25/2007 之间的差异应为 1 天;
但是,如果您在英国运行此路线,则使用毫秒路线,您将获得 0 天!
实现此目的的更好方法是使用 java.util.Calendar
Using millisecond approach can cause problems in some locales.
Lets take, for example, the difference between the two dates 03/24/2007 and 03/25/2007 should be 1 day;
However, using the millisecond route, you'll get 0 days, if you run this in the UK!
Better way to implement this is to use java.util.Calendar
您可以通过多种方法找到日期和日期之间的差异。次。我所知道的最简单的方法之一是:
print 语句只是一个示例 - 您可以按照您喜欢的方式格式化它。
There are many ways you can find the difference between dates & times. One of the simplest ways that I know of would be:
The print statement is just an example - you can format it, the way you like.
以毫秒为单位减去日期是可行的(如另一篇文章中所述),但在清除日期的时间部分时,您必须使用 HOUR_OF_DAY 而不是 HOUR:
Subtracting the dates in milliseconds works (as described in another post), but you have to use HOUR_OF_DAY and not HOUR when clearing the time parts of your dates:
如果你不想使用JodaTime或类似的,最好的解决方案可能是这样的:
每天的毫秒数并不总是相同的(因为夏令时和闰秒),但它非常接近,并且至少有偏差由于夏令时会在较长时间内取消。因此,除法然后舍入将给出正确的结果(至少只要使用的本地日历不包含除 DST 和闰秒之外的奇怪时间跳跃)。
请注意,这仍然假设
date1
和date2
设置为一天中的同一时间。正如 Jon Skeet 所指出的,对于一天中的不同时间,您首先必须定义“日期差异”的含义。If you don't want to use JodaTime or similar, the best solution is probably this:
The number of ms per day is not always the same (because of daylight saving time and leap seconds), but it's very close, and at least deviations due to daylight saving time cancel out over longer periods. Therefore dividing and then rounding will give a correct result (at least as long as the local calendar used does not contain weird time jumps other than DST and leap seconds).
Note that this still assumes that
date1
anddate2
are set to the same time of day. For different times of day, you'd first have to define what "date difference" means, as pointed out by Jon Skeet.看一下 Joda Time,它是一个改进的 Java 日期/时间 API,应该与 Scala 配合良好。
Take a look at Joda Time, which is an improved Date/Time API for Java and should work fine with Scala.
让我展示一下 Joda 间隔和天数之间的区别:
Let me show difference between Joda Interval and Days:
如果您需要格式化的返回字符串,例如
“2 天 03h 42m 07s”,试试这个:
If you need a formatted return String like
"2 Days 03h 42m 07s", try this:
在浏览完所有其他答案后,为了保留 Java 7 Date 类型,但使用 Java 8 diff 方法更加精确/标准,
After wading through all the other answers, to keep the Java 7 Date type but be more precise/standard with the Java 8 diff approach,
注意:startDate 和 endDate 为 -> java.util.Date
与天类似,也可以获取小时、分钟和秒
Note: startDate and endDates are -> java.util.Date
Similar to days, you can also get hours, minutes and seconds
检查此处的示例 http://www.roseindia.net/java/beginners/DateDifferent.shtml< /a>
这个例子给出了天、小时、分钟、秒和毫秒的差异:)。
Check example here http://www.roseindia.net/java/beginners/DateDifferent.shtml
This example give you difference in days, hours, minutes, secs and milli sec's :).
使用GMT时区获取Calendar的实例,使用Calendar类的set方法设置时间。 GMT 时区的偏移量为 0(并不重要),夏令时标志设置为 false。
Use GMT time zone to get an instance of the Calendar, set the time using the set method of Calendar class. The GMT timezone has 0 offset (not really important) and daylight saving time flag set to false.
以下代码可以为您提供所需的输出:
Following code can give you the desired output:
最好的做法是
该数字是一天中的毫秒数。
一个日期与另一个日期之间的差异以毫秒为单位。
将答案收集到 double 变量中。
Best thing to do is
That number is the number of milliseconds in a day.
One date-other date gives you difference in milliseconds.
Collect the answer in a double variable.
这是 O(1) 的正确 Java 7 解决方案,没有任何依赖项。
Here's a correct Java 7 solution in O(1) without any dependencies.
这可能是最直接的方法 - 也许是因为我已经用 Java 编码(其无可否认的笨重的日期和时间库)有一段时间了,但该代码对我来说看起来“简单而漂亮”!
您对以毫秒为单位返回的结果是否满意,或者您希望以某种替代格式返回结果?
That's probably the most straightforward way to do it - perhaps it's because I've been coding in Java (with its admittedly clunky date and time libraries) for a while now, but that code looks "simple and nice" to me!
Are you happy with the result being returned in milliseconds, or is part of your question that you would prefer to have it returned in some alternative format?
不使用标准 API,不。您可以自己做这样的事情:
或者您可以使用 Joda:
Not using the standard API, no. You can roll your own doing something like this:
Or you can use Joda:
只是回答最初的问题:
将以下代码放入像 Long getAge(){} 这样的函数中,
这里最重要的是在乘法和除法时处理长数字。当然,还有 Java 在日期计算中应用的偏移量。
:)
Just to answer the initial question:
Put the following code in a Function like Long getAge(){}
The most important here is to work with long numbers when multiplying and dividing. And of course, the offset that Java applies in its calculus of Dates.
:)
由于问题是用 Scala 标记的,
Since the question is tagged with Scala,
如果您想修复跨夏令时边界的日期范围问题(例如,一个日期为夏季时间,另一个日期为冬季时间),您可以使用此方法获取天数差异:
If you want to fix the issue for date ranges that cross daylight savings time boundary (e.g. one date in summer time and the other one in winter time), you can use this to get the difference in days: