我有......
Date start = new Date()
...
...
...
Date stop = new Date()
我希望在这两个日期之间获得数年,数月,日,时,分和秒。
-
我会改进这个问题。
我只想把经过的时间作为一个绝对的衡量标准,不考虑闰年,每个月的日子等等。
因此,我认为过去几年和几个月都是不可能的,我能得到的只是天,小时,分钟和秒。
更具体地说,我想告诉某个任务持续到例如
20 sec
13 min, 4 sec
2 h, 10 min, 2 sec
4 d, 4 h, 2 min, 2 sec
请原谅我的精确度不足。
答案 0 :(得分:91)
我刚刚发现了这个快速的Groovy源解决方案:
import groovy.time.TimeCategory
import groovy.time.TimeDuration
TimeDuration td = TimeCategory.minus( stop, start )
println td
答案 1 :(得分:25)
你可以用division和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;
这应该会为您提供所需的所有信息。
编辑:由于人们似乎感到困惑,不,这不会考虑闰年或夏令时转换等因素。这是纯粹过去的时间,这是opensas要求的。答案 2 :(得分:19)
使用标准Date API不太容易。
我不是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());
答案 3 :(得分:10)
关于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());
(不确定这是否有助于原始问题,但肯定是搜索者)。
答案 4 :(得分:6)
从Java 1.5开始,你应该使用TimeUnit.
这是一个简单的&简单的例子。我认为在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";
}
哦,请避免多次退货;)
答案 5 :(得分:6)
实际上,关于Joda-Time的上述答案。
使用Joda-Time的Period课程有一种更简单的方法:
Period period = new Period(startDate, endDate);
System.out.println(PeriodFormat.getDefault().print(period));
要自定义输出,请查看PeriodFormat,PeriodFormatter和PeriodFormatterBuilder类。
答案 6 :(得分:6)
Duration.between( then , Instant.now() )
现代方法使用java.time类来取代麻烦的旧日期时间类。
而不是Date
,请使用Instant
。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
Instant then = Instant.now();
…
Instant now = Instant.now();
使用Duration
类连接时间线的时间跨度,分辨率为day-hours-minutes-seconds-nanos。
Duration d = Duration.between( then , now );
在解决了几年 - 几天的时间段内,请使用Period
课程。
生成字符串为标准ISO 8601格式for durations:PnYnMnDTnHnMnS
。 P
标志着开始。 T
将任何年 - 月 - 天与小时 - 分 - 秒分开。所以两个半小时是PT2H30M
。
String output = d.toString();
在Java 9及更高版本中,您可以使用方法toDaysPart
,toHoursPart
等访问各个部分。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 7 :(得分:3)
开始= 2001年1月1日,上午10:00:00.000和
停止= 2003年1月6日,下午12:01:00.000
你想得到2年,0个月,5天,2小时,1分钟的答案
不幸的是,这是一个似是而非的答案。如果日期是1月2日和1月31日怎么办?那会是29天吗?好的,但是2月2日到3月2日是28(29)天,但会被列为1个月?
在不知道上下文的情况下,除了秒或可能天以外的任何时间长度都是可变的,因为月份和年份的长度不同。 2个日期之间的差异应该是静态单位,可以通过stop.getTime() - start.getTime()(这是毫秒的差异)很容易计算出来
答案 8 :(得分:3)
除了前面提到的 推荐的优秀JodaTime API之外,您可以使用的最佳标准Java替代方法是java.util.Calendar
。使用它是麻烦的(这是一种保守措施......请看这里的单行JodaTime示例),但您也可以使用它来计算经过的时间。重要的一点是,您应该在循环中使用Calendar#add()
来获取将闰日,年和几个世纪考虑在内的年,月和日的经过值。你不应该从(毫秒)开始计算它们。
这是一个基本的例子:
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;
}
}
它应该打印我现在的年龄=)
哦,我应该补充一下,您可以使用Date
将Calendar
“转换”为Calendar#setTime()
。
答案 9 :(得分:1)
这很容易;您应该设置正确的时区
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);
}
返回:
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
答案 10 :(得分:0)
创建Date对象毫无意义,因为所有这一切都包装了System.currentTimeMillis()。 getTime()函数只是解开Date对象。我建议你只需使用此功能即可获得很长时间。
如果你只需要第二个准确度,这很好。但是,如果您想要亚毫秒精度,请使用System.nanoTime()来获取经过的时间。
答案 11 :(得分:0)
这是我基于 Sebastian Celis 回答实施的完整功能。再次,从他的帖子 - ,这不会考虑像闰年或夏令时转换的事情。这是纯粹的经过时间。
输出是根据我的需要量身定制的。这仅输出三个重要部分。而不是返回
4个月,2周,3天,7小时,28分钟,43秒
它只返回前3个块(查看更多样本在帖子末尾运行):
4个月,2周,3天
以下是完整的方法源代码:
/**
* Format milliseconds to elapsed time format
*
* @param time difference in milliseconds
* @return Human readable string representation - eg. 2 days, 14 hours, 5 minutes
*/
public static String formatTimeElapsedSinceMillisecond(long milisDiff) {
if(milisDiff<1000){ return "0 second";}
String formattedTime = "";
long secondInMillis = 1000;
long minuteInMillis = secondInMillis * 60;
long hourInMillis = minuteInMillis * 60;
long dayInMillis = hourInMillis * 24;
long weekInMillis = dayInMillis * 7;
long monthInMillis = dayInMillis * 30;
int timeElapsed[] = new int[6];
// Define time units - plural cases are handled inside loop
String timeElapsedText[] = {"second", "minute", "hour", "day", "week", "month"};
timeElapsed[5] = (int) (milisDiff / monthInMillis); // months
milisDiff = milisDiff % monthInMillis;
timeElapsed[4] = (int) (milisDiff / weekInMillis); // weeks
milisDiff = milisDiff % weekInMillis;
timeElapsed[3] = (int) (milisDiff / dayInMillis); // days
milisDiff = milisDiff % dayInMillis;
timeElapsed[2] = (int) (milisDiff / hourInMillis); // hours
milisDiff = milisDiff % hourInMillis;
timeElapsed[1] = (int) (milisDiff / minuteInMillis); // minutes
milisDiff = milisDiff % minuteInMillis;
timeElapsed[0] = (int) (milisDiff / secondInMillis); // seconds
// Only adds 3 significant high valued units
for(int i=(timeElapsed.length-1), j=0; i>=0 && j<3; i--){
// loop from high to low time unit
if(timeElapsed[i] > 0){
formattedTime += ((j>0)? ", " :"")
+ timeElapsed[i]
+ " " + timeElapsedText[i]
+ ( (timeElapsed[i]>1)? "s" : "" );
++j;
}
} // end for - build string
return formattedTime;
} // end of formatTimeElapsedSinceMillisecond utility method
以下是一些示例测试声明:
System.out.println(formatTimeElapsedSinceMillisecond(21432424234L));
// Output: 8 months, 1 week, 1 day
System.out.println(formatTimeElapsedSinceMillisecond(87724294L));
// Output: 1 day, 22 minutes, 4 seconds
System.out.println(formatTimeElapsedSinceMillisecond(123434L));
// Output: 2 minutes, 3 seconds
答案 12 :(得分:0)
这是另一个类似的功能,如果需要,它不会显示天,小时,分钟等,如果不需要更改其文字。
public class ElapsedTime {
public static void main(String args[]) {
long start = System.currentTimeMillis();
start -= (24 * 60 * 60 * 1000 * 2);
start -= (60 * 60 * 1000 * 2);
start -= (60 * 1000 * 3);
start -= (1000 * 55);
start -= 666;
long end = System.currentTimeMillis();
System.out.println(elapsedTime(start, end));
}
public static String elapsedTime(long start, long end) {
String auxRet = "";
long aux = end - start;
long days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
// days
if (aux > 24 * 60 * 60 * 1000) {
days = aux / (24 * 60 * 60 * 1000);
}
aux = aux % (24 * 60 * 60 * 1000);
// hours
if (aux > 60 * 60 * 1000) {
hours = aux / (60 * 60 * 1000);
}
aux = aux % (60 * 60 * 1000);
// minutes
if (aux > 60 * 1000) {
minutes = aux / (60 * 1000);
}
aux = aux % (60 * 1000);
// seconds
if (aux > 1000) {
seconds = aux / (1000);
}
milliseconds = aux % 1000;
if (days > 0) {
auxRet = days + " days ";
}
if (days != 0 || hours > 0) {
auxRet += hours + " hours ";
}
if (days != 0 || hours != 0 || minutes > 0) {
auxRet += minutes + " minutes ";
}
if (days != 0 || hours != 0 || minutes != 0 || seconds > 0) {
auxRet += seconds + " seconds ";
}
auxRet += milliseconds + " milliseconds ";
return auxRet;
}
}
答案 13 :(得分:0)
我通常这样做:
def start_time = System.currentTimeMillis()
...
def end_time = System.currentTimeMillis()
println (end_time - start_time) +' ms'
然后,您可以使用Duration Groovy类http://docs.groovy-lang.org/latest/html/api/groovy/time/Duration.html将其分为所需的任何时间单位。
答案 14 :(得分:0)
import groovy.time.TimeCategory
import groovy.time.TimeDuration
time = { closure ->
use(TimeCategory) {
def started = new Date()
def res = closure()
TimeDuration duration = new Date() - started
logger.info("Execution duration: " + duration.toMilliseconds() + "ms")
res
}
}
time {
println 'A realy heavy operation here that you want to measure haha'
}
答案 15 :(得分:-1)
这是一个问题,需要考虑算法来计算闰年以及几年之后的确切月数和天数。有趣的是,如果只使用一个计量单位,它很简单。例如,两天之间的总天数是正确的,因为它与提醒天数相比,在数月和数年之后计算在二十年之内。
我目前正致力于从我的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:", .]
当然,这对于精确的利率计算也很有用。