在 Java/Groovy 中计算经过的时间
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/567659/
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
Calculate elapsed time in Java / Groovy
提问by opensas
I have...
我有...
Date start = new Date()
...
...
...
Date stop = new Date()
I'd like to get the years, months, days, hours, minutes and seconds ellapsed between these two dates.
我想得到这两个日期之间经过的年、月、日、小时、分钟和秒。
--
——
I'll refine the question.
我会细化问题。
I just want to get the elapsed time, as an absolute measure, that is without taking into account leap years, the days of each month, etc.
我只想得到经过的时间,作为一个绝对的衡量标准,即不考虑闰年、每个月的天数等。
Thus I think it's impossible to get the years and months elapsed, all I can get is days, hours, minutes and seconds.
因此,我认为不可能过去几年和几个月,我所能得到的只是几天、几小时、几分钟和几秒钟。
More specifically I want to tell that a certain task lasted for e.g.
更具体地说,我想说明某项任务持续了例如
20 sec
13 min, 4 sec
2 h, 10 min, 2 sec
4 d, 4 h, 2 min, 2 sec
So please forgive my lack of precision.
所以请原谅我不够精确。
回答by toolkit
Not so easy with the standard Date API.
使用标准 Date API 并不容易。
You might want to look at Joda Time, or JSR-310instead.
I'm not an expert in Joda, but I think the code would be:
我不是 Joda 的专家,但我认为代码是:
Interval interval = new Interval(d1.getTime(), d2.getTime());
Period period = interval.toPeriod();
System.out.printf(
"%d years, %d months, %d days, %d hours, %d minutes, %d seconds%n",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds());
回答by billjamesdev
Hmm, if I get what you're asking, you want to know that if:
嗯,如果我明白你的要求,你想知道如果:
start = Jan 1, 2001, 10:00:00.000 am and
开始时间 = 2001 年 1 月 1 日,上午 10:00:00.000 和
stop = Jan 6, 2003, 12:01:00.000 pm
停止 = 2003 年 1 月 6 日,下午 12:01:00.000
you want an answer of 2 years, 0 months, 5 days, 2 hours, 1 minute
你想要一个2年0个月5天2小时1分钟的答案
Unfortunately, this is a specious answer. What if the dates were Jan 2, and Jan 31? Would that be 29 days? Ok, but Feb 2 to Mar 2 is 28 (29) days, but would be listed as 1 month?
不幸的是,这是一个似是而非的答案。如果日期是 1 月 2 日和 1 月 31 日怎么办?那会是29天吗?好的,但是 2 月 2 日到 3 月 2 日是 28 (29) 天,但会被列为 1 个月吗?
The length of time in anything other than seconds or possibly days is variable without knowing the context since months and years are of different lengths. The difference between 2 dates should be in static units, which are easily computable from stop.getTime() - start.getTime() (which is the difference in millisecs)
由于月份和年份的长度不同,因此在不知道上下文的情况下,除秒或可能的天之外的任何时间长度都是可变的。2 个日期之间的差异应该是静态单位,这很容易从 stop.getTime() - start.getTime() 计算出来(以毫秒为单位的差异)
回答by Sebastian Celis
You can do all of this with division and mod.
您可以使用除法和 mod 来完成所有这些操作。
long l1 = start.getTime();
long l2 = stop.getTime();
long diff = l2 - l1;
long secondInMillis = 1000;
long minuteInMillis = secondInMillis * 60;
long hourInMillis = minuteInMillis * 60;
long dayInMillis = hourInMillis * 24;
long elapsedDays = diff / dayInMillis;
diff = diff % dayInMillis;
long elapsedHours = diff / hourInMillis;
diff = diff % hourInMillis;
long elapsedMinutes = diff / minuteInMillis;
diff = diff % minuteInMillis;
long elapsedSeconds = diff / secondInMillis;
That should give you all of the information you requested.
这应该为您提供您要求的所有信息。
EDIT: Since people seem to be confused, no, this does not take things like leap years or daylight savings time switches into account. It is pure elapsed time, which is what opensas asked for.
编辑:由于人们似乎很困惑,不,这并没有考虑闰年或夏令时切换之类的事情。这是纯粹的流逝时间,这就是 opensas 所要求的。
回答by Fletch
Regarding JodaTime I just got it going; thanks to the responder who suggested it. Here's a more condensed version of the Joda code suggested:
关于 JodaTime 我刚刚开始;感谢提出它的响应者。这是建议的 Joda 代码的更精简版本:
Period period = new Period(d1.getTime(), d2.getTime());
System.out.printf(
"%d years, %d months, %d days, %d hours, %d minutes, %d seconds%n",
period.getYears(), period.getMonths(), period.getDays(),
period.getHours(), period.getMinutes(), period.getSeconds());
(not sure if this is helping the original question but certainly searchers).
(不确定这是否有助于原始问题,但肯定是搜索者)。
回答by Peter Lawrey
There is no point creating a Date object as all this does is wrap System.currentTimeMillis(). The getTime() function just unwraps the Date object. I suggest you just use this function to obtain a long.
创建 Date 对象是没有意义的,因为它所做的只是包装 System.currentTimeMillis()。getTime() 函数只是解开 Date 对象。我建议你只使用这个函数来获得一个长的。
If you only need second accuracy, this is fine. However if you want sub-millisecond accuracy use System.nanoTime() to get the elapse time.
如果您只需要第二个精度,这很好。但是,如果您想要亚毫秒级精度,请使用 System.nanoTime() 来获取经过时间。
回答by BalusC
Apart from the aforementioned great JodaTimeAPI which I dorecommend, the best standard Java alternative you can have is the java.util.Calendar
. It is cumbersometo work with it (this is an understatement .. look at the single-line JodaTime examples here), but you can calculate the elapsed time with it as well. Important key is that you should use the Calendar#add()
in a loop to get the elapsed value for years, months and days to take leap days, years and centuries into account. You should not calculate them back from the (milli)seconds.
除了上述大JodaTimeAPI,我不推荐,最好的标准Java替代你可以是java.util.Calendar
。使用它很麻烦(这是轻描淡写的……看看这里的单行 JodaTime 示例),但您也可以使用它计算经过的时间。重要的关键是您应该使用Calendar#add()
循环来获取年、月和日的经过值,以将闰日、年和世纪考虑在内。您不应该从(毫秒)秒开始计算它们。
Here's a basic example:
这是一个基本示例:
import java.util.Calendar;
public class Test {
public static void main(String[] args) throws Exception {
Calendar start = Calendar.getInstance();
start.set(1978, 2, 26, 12, 35, 0); // Just an example.
Calendar end = Calendar.getInstance();
Integer[] elapsed = new Integer[6];
Calendar clone = (Calendar) start.clone(); // Otherwise changes are been reflected.
elapsed[0] = elapsed(clone, end, Calendar.YEAR);
clone.add(Calendar.YEAR, elapsed[0]);
elapsed[1] = elapsed(clone, end, Calendar.MONTH);
clone.add(Calendar.MONTH, elapsed[1]);
elapsed[2] = elapsed(clone, end, Calendar.DATE);
clone.add(Calendar.DATE, elapsed[2]);
elapsed[3] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 3600000;
clone.add(Calendar.HOUR, elapsed[3]);
elapsed[4] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 60000;
clone.add(Calendar.MINUTE, elapsed[4]);
elapsed[5] = (int) (end.getTimeInMillis() - clone.getTimeInMillis()) / 1000;
System.out.format("%d years, %d months, %d days, %d hours, %d minutes, %d seconds", elapsed);
}
private static int elapsed(Calendar before, Calendar after, int field) {
Calendar clone = (Calendar) before.clone(); // Otherwise changes are been reflected.
int elapsed = -1;
while (!clone.after(after)) {
clone.add(field, 1);
elapsed++;
}
return elapsed;
}
}
It should print my age as of now =)
它应该打印我现在的年龄 =)
Oh, I should add, you can "convert" Date
to Calendar
using Calendar#setTime()
.
哦,我应该补充一下,您可以“转换”Date
为Calendar
使用Calendar#setTime()
.
回答by pd.
I've just discovered this quick Groovy-sourced solution:
我刚刚发现了这个源自 Groovy 的快速解决方案:
import groovy.time.TimeCategory
import groovy.time.TimeDuration
Date start = new Date()
// do something here
Date stop = new Date()
TimeDuration td = TimeCategory.minus( stop, start )
println td
回答by dhesse
Well since Java 1.5 you should use TimeUnit.
好吧,从 Java 1.5 开始,您应该使用TimeUnit。
Here is a simple & plain example for this. I think in groovy it might get shorter(as always).
这是一个简单而简单的例子。我认为在 groovy 中它可能会变短(一如既往)。
/**
* Formats a given {@link Date} to display a since-then timespan.
* @param created
* @return String with a format like "3 minutes ago"
*/
public static String getElapsedTime(Date created) {
long duration = System.currentTimeMillis() - created.getTime();
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration);
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration);
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration);
if (days > 0) {
return days + " days";
}
if (hours > 0) {
return hours + " hrs";
}
if (minutes > 0) {
return minutes + " minutes";
}
return seconds + " seconds";
}
Oh and avoid multiple returns please ;)
哦,请避免多次退货;)
回答by udoline
It's easy; You should set the right timezone
这很简单; 您应该设置正确的时区
import java.util.TimeZone;
import java.util.logging.Logger;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public class ImportData {
private final static Logger log = Logger.getLogger(ImportData.class.getName());
private final static DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS");
private final static DateTimeFormatter dtfh = DateTimeFormat.forPattern("HH:mm:ss.SSS");
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
DateTimeZone.setDefault(DateTimeZone.forID("Europe/Berlin"));
// Quotes connection=Quotes.getInstance();
final long start = System.currentTimeMillis();
// do something here ...
// connection.importTickdata();
Thread.currentThread().sleep(2000);
final long end = System.currentTimeMillis();
log.info("[start] " + dtf.print(start));
log.info("[end] " + dtf.print(end));
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
DateTimeZone.setDefault(DateTimeZone.forID("UTC"));
log.info("[duration] " + dtfh.print(end - start));
// connection.logOff();
// System.exit(0);
}
returns:
返回:
10.11.2010 00:08:12 ImportData main INFO: [start] 2010-11-10 00:08:10.306 10.11.2010 00:08:12 ImportData main INFO: [end] 2010-11-10 00:08:12.318 10.11.2010 00:08:12 ImportData main INFO: [duration] 00:00:02.012
回答by buda
This is a problem and an algorithm needs to be made to account for leap years and exact amount of months and days beside years. Interesting how it is simple if only one unit of measure is to be used. For example, total number of days between two days is correct as apposed to reminder number of days after number of months and years is calculate within let's say two decades.
这是一个问题,需要制定一种算法来考虑闰年和年份之外的确切月数和天数。有趣的是,如果只使用一种度量单位,它是多么简单。例如,两天之间的总天数是正确的,因为在月份数和年份数之后的提醒天数是在假设的二十年内计算的。
I am currently working on this to provide it from my PML implementation, for example, in the form of:
我目前正在致力于从我的 PML 实现中提供它,例如,以以下形式提供:
unemployed <- date.difference[
From = 2009-07-01,
Till = now,
YEARS, MONTHS, DAYS
]: yyyy-MM-dd
$$-> *unemployed -> date.translate[ YEARS, MONTHS, DAYS ] -> print["Unemployed for:", .]
Of course, this would also be useful and required for exact interest rate calculations.
当然,这对于精确的利率计算也是有用的和必需的。