将经过的毫秒数转换为Java日期格式?

3
我被困在开发过程中,有一个要求需要我找到两个日期之间的延迟,即当前日期-从数据库中取出的日期。我需要以dd:hh:mm的格式显示延迟。在参考了很多资料后,我发现如何将时间转换为毫秒、小时和分钟,但是我期望的是:如果结果是X毫秒,则需要以正确的天、分钟和秒格式显示结果。 示例:2天3分钟46秒 以下是我正在使用的代码:
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.setTime(date);
calendar2.setTime(date1);
long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds1 - milliseconds2;
System.out.println("diff ::"+diff);
long diffSeconds = diff / 1000;
long diffMinutes = diff / (60 * 1000);
long diffHours = diff / (60 * 60 * 1000);
long diffDays = diff / (24 * 60 * 60 * 1000);

有人能建议我接下来该怎么做吗?请给我指导。


1
在那段代码中,你假设每天有24小时,每小时60分钟,每分钟有60秒。这在使用夏令时的国家或者存在闰秒的星球上是行不通的。你应该使用像Joda Time这样的日历框架,让它来处理繁重的工作。 - wallenborn
@wallenborn,现在正在对joda time进行后台工作,你能帮我解释一下如何使用它吗? - Esh
请注意,像java.util.Datejava.util.Calendarjava.text.SimpleDateFormat这样的老旧日期时间类现在已经成为遗留系统,被内置于Java 8及更高版本中的java.time类所取代。请参阅Oracle的教程 - Basil Bourque
6个回答

8
使用Joda Time。Java API没有处理“两个日期/时间值之间的差异”的任何内容。在Joda Time中,您可以选择Period(这实际上是一个基于日历的差异)和Duration(这实际上只是经过的时间差异)。
理想情况下,使用Joda Time来处理所有与日期/时间有关的问题 - 它是一个更好的API。
在这种情况下,我怀疑您已经逻辑上获得了一个Duration,但您将需要将其转换为一个Period,以便使用PeriodFormatter进行字符串转换。

请问您能否提供一些Joda Time的示例? - Esh
@Esh:嗯,你试了什么? - Jon Skeet
到目前为止,我尝试分别获取小时和分钟,现在在时间顺序的概念上遇到了困难。我想将时间顺序设置为'000',但它默认为ISOChronology[Asia/Kolkata],不知道如何覆盖它。 - Esh
@Esh:你说的“000”是什么意思?听起来你可能想要使用ISOChronology.getInstanceUTC - Jon Skeet
我会在http://stackoverflow.com/questions/13577222/how-to-use-joda-date-and-time-api上发布我的工作。请指导我。 - Esh

3
你需要先计算diffDays
diffDays = diff / (24 * 60 * 60 * 1000);

然后计算剩余的毫秒数:
diff -= diffDays * 24 * 60 * 60 * 1000;

使用新的diff计算diffHours等等...

一个建议:使用如下的常量值:

private static final int SECOND = 1000;
private static final int MINUTE = 60 * SECOND;
// and so on

丹,你能否请稍微详细地解释一下给我? - Esh
这假设每天有24小时,如果你生活在一个有夏令时的地区,每年会失败两次。 - wallenborn
你能找到哪些其他边缘情况?也许你可以为每个情况投反对票。 - Dan D.

1

使用JodaTime很容易。请看以下代码:

public void testJoda() {
    DateTime then = new DateTime("2012-03-23T02:30:00.000");
    DateTime now = new DateTime("2012-03-24T02:29:00.000");

    DurationFieldType[] ddhhmm = { DurationFieldType.days(),
            DurationFieldType.hours(), DurationFieldType.minutes() };
    Period p = new Period(then, now, PeriodType.forFields(ddhhmm));
    System.out.println(p.toString());

    p = new Period(then, now, PeriodType.days());
    System.out.println(p.toString());

    p = new Period(then, now, PeriodType.hours());
    System.out.println(p.toString());

    DurationFieldType[] hhmm  = { DurationFieldType.hours(), DurationFieldType.minutes() };
    p = new Period(then, now, PeriodType.forFields(hhmm));
    System.out.println(p.toString());
}

这个测试持续23小时59分钟的间隔。其输出符合预期:

PT23H59M
P0D
PT23H
PT23H59M

在同样的时间间隔内,一天后,就在3月25日春季DST跳跃周围:

DateTime then = new DateTime("2012-03-24T02:30:00.000");
DateTime now = new DateTime("2012-03-25T03:29:00.000");

你正确地得到:

P1DT-1M
P1D
PT23H
PT23H59M

实在没有比那更简单的了。


FYI,Joda-Time 项目现已进入维护模式,团队建议迁移到java.time类。请参阅Oracle的教程 - Basil Bourque

1

- 当你处理任何日期时间问题时,我建议使用Joda库。

Joda Time有一个时间间隔的概念:

Interval interval = new Interval(oldTime, new Instant());

顺便说一下,Joda有两个概念:Interval用于表示两个时间瞬间之间的时间间隔(表示8点到10点之间的时间),而Duration表示没有实际时间边界的时间长度(例如表示两小时!)


FYI,Joda-Time 项目现已进入维护模式,团队建议迁移到java.time类。请参阅Oracle的教程 - Basil Bourque

0

简而言之

Duration.between(   // Represent a span of time, unattached to the timeline.
    earlier ,       // `Instant` class represents a moment in UTC with a resolution as fine as nanoseconds. Current moment captured in microseconds, depending on capability of host computer hardware and operating system.
    Instant.now()
)                   // Returns a `Duration` object. Call `to…Part` methods to get the days, hours, minutes, seconds as separate numbers.

java.time

使用现代的java.time类比早期版本的Java中捆绑的麻烦的旧日期时间类要容易得多。

获取当前时刻的UTC时间。Instant类表示UTC时间线上的一个时刻,其分辨率为纳秒(最多九个小数位)。

在Java 8中,当前时刻以毫秒为单位捕获。在Java 9及更高版本中,由于对Clock进行了新的实现,您可能会看到以更精细的粒度捕获当前时刻。在macOS Sierra上的Oracle Java 9 JDK中,我以微秒(六位小数秒)获取当前时刻。

Instant earlier = Instant.now() ;
…
Instant later = Instant.now() ;

计算经过的时间,作为与时间轴无关的时间跨度。对于以小时-分钟-秒为刻度(并将一天视为与日历无关的24小时时间块),请使用{{link1:Duration}}。对于以年-月-日为刻度,请使用Period

Duration d = Duration.between( earlier , later ) ;

生成一个字符串是 标准 ISO 8601 格式, PnYnMnDTnHnMnS,其中P表示开始,T将年-月-日与时-分-秒分开。
String output = d.toString() ;  // Standard ISO 8601 format.

我强烈建议使用标准格式而不是问题中所见的格式。我曾经看到过时间格式引起了很多混乱和歧义,因为它可能被误认为是一段时间而不是一段时间跨度。ISO 8601格式明智地设计以避免这种歧义。但如果您坚持使用,在Java 9及更高版本中,您可以通过调用to...Part方法来请求Duration的部分。

long days = d.toDaysPart() ;  // 24-hour chunks of time, unrelated to calendar dates.
int hours = d.toHoursPart() ;
int minutes = d.toMinutesPart() ;

然后按照您的需求将其组装成一个字符串。


关于java.time

Java.time框架是在Java 8及更高版本中内置的。这些类替代了老旧的传统日期时间类,例如{{link3:java.util.Date}}、 {{link4:Calendar}}和{{link5:SimpleDateFormat}}。

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

想要了解更多,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是 JSR 310

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。无需字符串,也不需要 java.sql.* 类。

如何获取 java.time 类?

ThreeTen-Extra 项目通过添加额外的类扩展了 java.time。该项目是 java.time 可能未来增加内容的试验场。您可能会在这里找到一些有用的类,例如 Interval, YearWeek, YearQuarter更多


0
Calendar calendar1 = Calendar.getInstance();
Calendar calendar2 = Calendar.getInstance();
calendar1.setTime(date);
calendar2.setTime(date1);

int dayDiff = calendar1.get(Calendar.DAY_OF_MONTH) - calendar2.get(Calendar.DAY_OF_MONTH);  
int hourDiff = calendar1.get(Calendar.HOUR_OF_DAY) -calendar2.get(Calendar.HOUR_OF_DAY);   
int dayDiff = calendar1.get(Calendar.SECOND) - calendar2.get(Calendar.SECOND);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接