【问题标题】:How to represent just 'time' with JodaTime如何用 JodaTime 表示“时间”
【发布时间】:2020-04-24 14:55:37
【问题描述】:

我不知道如何只解释“时间”,所以我想从一个例子开始。
当我写一个电影播放器​​时,我想以毫秒为单位表示开始时间(00:00:00)为 0,如果当前帧位置在 5 分钟(00:05:00)上,则为 300,000(5 * 60 * 1000)。
我不在乎现实世界中的时区、日历或时钟信息。

但是,例如 JodaTime,Instant 与 Unixtime 相关(基于 1970),IntervalDurationPeriod 基于 Instant,而LocalTime 基于 24-小时(将小时字段强制为 1-24)。

当然,我可以手动将“00:05:00”解析为 300,000,但我想知道如何使用 JodaTime 或其他库来实现这个目标。

【问题讨论】:

  • 您确定Duration 不是您想要的吗?我不确定 JodaTime,但 Java 时间 Duration(基于 JodaTime)就代表了一个持续时间。
  • 持续时间是一个时间跨度的长度,它准确地描述了你提到的概念。我同意 Slaw 的观点,因为我不明白为什么 Duration 不符合您的需求。
  • 顺便说一句,如果可以的话,您应该使用更新的 Java 日期和时间 API,在 java.time 包中提供,而不是 Joda Time。后者处于维护模式,他们自己的网站建议在 About 部分移至java.time
  • @Slaw 我认为Duration 是millis 持有人。没错,它没有时钟信息,但是Duration 需要millis 来实例化。否则,它提供parse 方法,但它需要特定的格式化字符串。无法将自定义格式化字符串(例如 00:05:00)转换为毫秒或 Duration。也无法将Duration 格式化为字符串。
  • 关于java.time pre Java 8的Android支持:github.com/JakeWharton/ThreeTenABP

标签: java android time jodatime


【解决方案1】:

Duration

您关于Duration 类的陈述不正确。你说它是基于Instant,但是,不,它不是。

Duration 表示时间跨度附加到时间线。 Joda-Time 中的Duration 只是毫秒数。这个事实在它的 Javadoc 中有说明。

Period 的情况同上,它表示与时间轴无关的时间跨度,范围为年-月-日。 Duration 在小时-分钟-秒的范围内工作。

表示五分钟的跨度:

Duration d = Duration.standardMinutes( 5 ) ;

如果您想通过该时间量获得未来的时刻,请将该持续时间添加到当前时刻。

Instant fiveMinutesInFuture =  new Instant().plus( d ) ;

ISO 8601

要将持续时间表示为文本,请使用标准 ISO 8601 格式,以 P 开头,T 将年-月-日部分与小时-分钟-秒部分分开。

所以五分钟是PT5M

String output = d.toString() ;

解析此类 ISO 8601 字符串。

Duration d = Duration.parse( "PT5M" ) ;  // Five minutes.

时钟格式

要将duration 对象序列化为文本,请始终使用 ISO 8601 标准格式,不要使用时钟格式。

对于用户界面演示,我建议您不要使用诸如00:05:00 之类的时钟符号来表示时间跨度。这样做会使用户感到困惑和模棱两可。请改用 ISO 8601 标准格式,因为它们旨在实用且明确。

如果您坚持以时钟时间格式表示持续时间,请调用getStandard… 方法来获取小时、分钟和秒。

String output = 
        String.format( "%02d", d.getStandardHours() ) + 
        ":" +
        String.format( "%02d", d.getStandardMinutes() ) +
        ":" +
        String.format( "%02d", d.getStandardSeconds() ) 
;

00:05:00

如果持续时间可能超过 24 小时,您还需要致电 getStandardDays。这些天只是 24 小时长的时间。由于Duration 未附加到时间线,因此这些日期不是 个日历日。

java.time

请注意,Joda-Time 现在处于维护模式。它的继任者 java.time 内置于 Java 8 及更高版本以及 Android 26+。对于 Java 6 和 7,请使用 ThreeTen-Backport。对于早期的 Android,请使用 ThreeTenABP

java.time 中的概念与此处讨论的相同。 java.time.Duration 类非常相似,除了更精细的纳秒分辨率和稍微不同的语法。

Instant.now().plus(
    Duration.ofMinutes( 5 )
)

或者:

Instant.now().plus(
    Duration.parse( "PT5M" )
)

要构建时钟读数,请调用to…Part 方法。

String output = 
        String.format( "%02d", d.toHoursPart() ) + 
        ":" +
        String.format( "%02d", d.toMinutesPart() ) +
        ":" +
        String.format( "%02d", d.toSecondsPart() ) 
;

00:05:00

【讨论】:

  • 我同意我的说法是错误的,但我在上面评论过,我找不到使用格式化字符串的方法。有没有办法将自定义格式的字符串转换为Duration 或反之亦然?
  • @khcpietro 您的问题不是关于解析,而是在最后提及。
  • “切勿使用诸如 00:05:00 之类的时钟符号来表示时间跨度。这样做会令人困惑和模棱两可,而且是一种不好的做法”。您是说不要persisttransport 使用时钟符号吗?因为计时器和秒表一直以这种格式显示持续时间。虽然公平地说,这只是表示(即格式化,而不是解析)。
  • @Slaw 也许吧。虽然我记得在早期的数字手表时代,许多人将秒表/计时器功能与时间混淆。做你认为合适的事。我建议以 ISO 8601 格式向用户展示持续时间,也许在字母之间添加空格。对用户的培训将是最少的。
  • 我想我只是从未见过在更多技术环境之外以 ISO 8601 格式呈现的持续时间。例如,我见过的每个烤箱和微波炉都使用时钟符号作为计时器。我手机上的计时器/秒表应用程序使用时钟符号。您经常在体育赛事中看到的那些手持秒表使用时钟符号。我的跑步手表使用时钟符号。体育运动使用时钟符号来显示比赛/半场/季度/期间/你有多少时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 2017-01-09
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多