将经过的毫秒转换为正确的 java 日期格式?

Posted

技术标签:

【中文标题】将经过的毫秒转换为正确的 java 日期格式?【英文标题】:Converting elapsed milliseconds into proper java date format? 【发布时间】:2012-11-13 18:06:41 【问题描述】:

我在开发过程中遇到困难,我有这样的要求,我需要找到两个日期之间的延迟,即..currentdate-date from database

我需要以 dd:hh:mm 的格式显示延迟。在参考了很多参考资料后,我发现了如何转换为单个毫秒的小时和分钟,但期待的是:如果结果是 X 毫秒,我需要以正确的日分钟和秒格式显示它

示例:2 天:03 分钟: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);

谁能建议我进一步做什么? 请指导我..

【问题讨论】:

在该代码中,您假设每天有 24 小时,每小时有 60 分钟,每分钟有 60 秒。这不适用于夏令时的国家,也不适用于闰秒的行星。您应该改用 Joda Time 之类的日历框架,并让它完成繁重的工作。 @wallenborn ,是的,现在在 joda time 做后台工作,你能帮我看看如何使用它 仅供参考,麻烦的旧日期时间类,例如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.见Tutorial by Oracle。 【参考方案1】:

使用Joda Time。 Java API 不包含任何处理“两个日期/时间值之间的差异”的内容。在 Joda Time 中,您可以在 Period(实际上是针对以日历为中心的差异)和 Duration(实际上只是经过的时间差异)之间进行选择。

理想情况下,将 Joda Time 用于所有您的日期/时间问题 - 这是一个更好、更好的 API。

在这种情况下,我怀疑您逻辑上得到了Duration,但您需要将其转换为Period,以便使用PeriodFormatter 进行字符串转换.

【讨论】:

你能提供一些joda time的例子吗 @Esh:嗯,你尝试了什么? 到目前为止,我尝试分别获取小时和分钟,现在我陷入了年表概念,我想将年表设置为“000”,但将默认设置为 ISOChronology[亚洲/加尔各答] ,不知道如何覆盖它 @Esh:你说的“000”是什么意思?听起来你可能想要ISOChronology.getInstanceUTC ,.我会在***.com/questions/13577222/… 中发布我的作品。请指导我【参考方案2】:

你需要先计算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

【讨论】:

丹,你能不能详细解释一下 这假设每天有 24 小时,如果你住在有夏令时的地区,每年都会失败两次。 您还能找到哪些其他极端情况?也许你可以对每一个投反对票。【参考方案3】:

-我建议您在处理任何日期时间问题时使用 Joda 库。

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

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

顺便说一下,Joda 有两个概念:Interval 表示两个时间点之间的时间间隔(表示上午 8 点到 10 点之间的时间),以及 Duration 表示没有实际时间界限的时间长度(例如表示两个小时!)

【讨论】:

仅供参考,Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。见Tutorial by Oracle。【参考方案4】:

有了 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());

测试间隔为 23h59m。它的输出符合预期:

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

真的,没有比这更容易的了。

【讨论】:

仅供参考,Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。见Tutorial by Oracle。【参考方案5】:
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);

【讨论】:

【参考方案6】:

tl;博士

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 时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。

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

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

将经过的时间计算为与时间轴无关的时间跨度。对于小时-分钟-秒(以及与日历无关的 24 小时时间块),请使用 Duration。对于年-月-日的比例,请使用Period

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

生成一个字符串是standard ISO 8601 format,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 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

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

从哪里获得 java.time 类?

Java SE 8Java SE 9Java SE 10 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6Java SE 7 ThreeTen-Backport 中的大部分 java.time 功能都向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

以上是关于将经过的毫秒转换为正确的 java 日期格式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在android中将毫秒转换为日期格式?

将iso日期格式的字符串转换为毫秒。 ISO日期格式包含(“ yyyy-MM-dd”),并且没有时区

vue.js怎样将时间戳转化为日期格式

java如何把时间格式转为毫秒

时间戳转为日期格式

Freemarker 以毫秒为单位将时间戳转换为带有时区的日期