【问题标题】:Converting Timestamp string "HH:mm:ss" to Duration将时间戳字符串“HH:mm:ss”转换为持续时间
【发布时间】:2016-07-17 11:55:40
【问题描述】:

正如标题所说,我已经能够从文本文件中分离出一个包含“HH:mm:ss”格式的持续时间的字符串。我将如何将其转换为持续时间?我需要将其转换为以 1 小时表示此时间戳的双精度数,因此如果它是“08:30:00”,我需要双精度数的值为 8.5。不确定如何进行转换,似乎时间在 Java 中是一个棘手的主题。任何帮助都将不胜感激,即使只是您说“使用此类”,以便我查找并弄清楚。

谢谢!

【问题讨论】:

  • 您可以使用parse 方法将字符串转换为本地时间。然后用 getSecond 方法除以 60 分钟得到。然后使用 getMinute 方法获取分钟,将秒转换的分钟相加除以 60 得到小时。然后将该值添加到该时间的 getHour 值。另一种方法是使用冒号拆分字符串并进行类似的计算。

标签: java string time timestamp duration


【解决方案1】:

您可以将表达式拆分为多个部分,然后解析并计算持续时间:

    String[] a = "08:30:00".split(":");
    double d = Integer.parseInt(a[0]) + Integer.parseInt(a[1]) / 60.0;

【讨论】:

  • 是的,这正是我想要的。不得不使用 d = d + Integer.parseInt(a[0]) + Integer.parseInt(a[1])/60.0 + Integer.parseInt(a[2])/3600.0;在这种情况下,要整合秒值,但你让我走上了正确的轨道。谢谢!
【解决方案2】:

tl;博士

Duration.between ( 
    LocalTime.MIN , 
    LocalTime.parse ( "08:30:00" ) 
).toString()

PT8H30M

持续时间与时间戳

如果字符串08:30:00 的意思是“八个半小时”的时间跨度,则不要使用术语“时间戳”。 “持续时间”这个词是正确且常用的。并避免使用 HH:MM:SS 的格式,因为它是如此模棱两可,看起来像是一天中的时间。而是使用下面讨论的标准格式。

如果字符串08:30:00 的意思是“早上八点半”,则使用“时间戳”一词并避免使用“持续时间”一词。

这是两个截然不同的概念。您必须弄清楚它们,每个都应该在您的脑海中是不同的。使用 HH:MM:SS 的模棱两可的格式使区分变得更加困难(所以避免使用这种格式!)。

java.time

现代方法是使用 java.time 类。

LocalTime

正如 Sharma 评论中提到的,首先将您的字符串解析为LocalTime。此类表示没有日期和时区的时间。没有时区意味着这些对象基于通用 24 小时制,而不考虑 Daylight Saving Time (DST) 等异常情况。

我们并不真正想要LocalTime,因为您的输入字符串代表时间跨度而不是一天中的某个时间。但这只是第一步。

LocalTime lt = LocalTime.parse ( "08:30:00" );

Duration

为了表示所需的时间跨度,我们需要 Duration 类。此类适用于未附加到时间线的时间跨度。我们可以通过转换LocalTime 来创建一个,方法是获取从时钟开始的时间量00:00:00.0LocalTime.MIN,以及我们刚刚实例化的lt

Duration d = Duration.between ( LocalTime.MIN , lt );

ISO 8601

我们可以通过调用Duration::toString 以标准ISO 8601 format for durations 生成一个字符串来查看结果。 java.time 类在解析/生成字符串时默认使用 ISO 8601。对于持续时间,标准格式为PnYnMnDTnHnMnS,其中P 标记开始,T 将年-月-日部分与小时-分钟-秒部分分开。因此,我们的八个半小时将显示为PT8H30M

System.out.println("d.toString():" + d);

d.toString(): PT8H30M

日期时间值避免使用小数

为了处理此类持续时间值,我强烈建议在您的 Java 代码中使用 Duration 对象,并在序列化为文本时使用 ISO 8601 格式。

  • 在代码中使用对象可提供类型安全性,使您的代码更具自记录性,并确保有效值。
  • 对文本使用 ISO 8601 格式可生成易于解析的值,是一种易于人类阅读的格式,并且其含义明确,而 08:30:00 可能会被误读为一天中的时间。李>

您想要的十进制数格式(如 8.5)不明确(容易忘记其含义)。此外,在使用 floating-point 类型(floatFloatdoubleDouble)时,十进制数字很尴尬并且经常不正确,因为这些类型会在小数部分的远端生成无关的不正确数字。浮点技术故意牺牲准确性以提高执行速度。

BigDecimal

如果您必须使用小数,并且想要准确,请使用BigDecimal 类。

在此示例中,我假设您在截断任何小数分钟时需要小时和分钟。所以我打电话给toMinutesDuration

BigDecimal minutesPerHour = new BigDecimal ( 60L ); // Use var/constant for clarity of your intent.
BigDecimal minutes = new BigDecimal ( d.toMinutes () );
BigDecimal fractionalHours = minutes.divide ( minutesPerHour );

fractionalHours.toString(): 8.5

请参阅此示例code live in IdeOne.com

如果您坚持使用这些小数而不是 Duration 对象和 ISO 8601 文本,您可能希望使用 BigDecimal 工具进行舍入。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

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

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

从哪里获得 java.time 类?

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

【讨论】:

    【解决方案3】:

    我会使用String.split() 来完成此操作。这将根据您在参数中指定的正则表达式/分隔符将其拆分为一个数组。像这样的,

    String time = "08:30:00";
    String[] splitValues = time.split(":");
    double hour = splitValue[0];
    double minute = splitValue[1];
    double seconds = splitValue[2];
    

    然后您可以将这些值相加。你知道一小时有60分钟,一分钟有60秒。您可以通过分别除以 60 和 3600 将这些转换为小时。那么,这只是一个简单的加法。

    【讨论】:

    • 不是正则表达式,但 split 方法使用正则表达式来拆分字符串。我会修改答案。
    猜你喜欢
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多