【问题标题】:Format Duration of Time格式持续时间
【发布时间】:2012-09-03 13:12:57
【问题描述】:

我整个上午都在试图找到一种方法来实现我最初认为相对容易的任务:将以数字方式表示的持续时间转换为可读的方式。例如,输入 3.5,输出应为“3 年零 6 个月”。

根据我正在阅读的内容,似乎强烈推荐 Joda Time 库。使用该库并关注this post 我正在尝试以下操作:

    Period p = new Period(110451600000L); // 3 years and a half

    PeriodFormatter formatter = new PeriodFormatterBuilder()
        .appendYears()
        .appendSuffix(" year", " years")
        .appendSeparator(" and ")
        .appendMonths()
        .appendSuffix(" month", " months")
        .toFormatter();

    System.out.println(formatter.print(p));

但是输出什么都没有。不知道为什么它不起作用。

我也试过Apache DurationFormatUtils,但不起作用。

有人有想法吗?

提前致谢。

【问题讨论】:

  • 也许您会对这个非常古老的答案感兴趣。 stackoverflow.com/a/12/559299
  • Hinton,非常感谢您的及时答复。尽管您建议的答案是针对 C#,但我想我可以轻松地调整算法。尽管如此,这将是我的最后一个解决方案,因为我相信应该有一种更简单、更清洁的方式来使用 Joda Time,例如。我的首要任务是避免重新发明轮子:D 再次感谢您的回答!

标签: java format jodatime duration


【解决方案1】:

经过一番研究、测试和benjamin的帮助,我有了一个解决方案:

    DateTime dt = new DateTime(); // Now
    DateTime plusDuration = dt.plus(new Duration(110376000000L)); // Now plus three years and a half

    // Define and calculate the interval of time
    Interval interval = new Interval(dt.getMillis(), plusDuration.getMillis());

    // Parse the interval to period using the proper PeriodType
    Period period = interval.toPeriod(PeriodType.yearMonthDayTime());

    // Define the period formatter for pretty printing the period
    PeriodFormatter pf = new PeriodFormatterBuilder()
            .appendYears().appendSuffix("y ", "y ")
            .appendMonths().appendSuffix("m", "m ").appendDays()
            .appendSuffix("d ", "d ").appendHours()
            .appendSuffix("h ", "h ").appendMinutes()
            .appendSuffix("m ", "m ").appendSeconds()
            .appendSuffix("s ", "s ").toFormatter();

    // Print the period using the previously created period formatter
    System.out.println(pf.print(period).trim());

我发现 Joda-Time 的官方文档非常有用,特别是这篇文章:Correctly defining a duration using JodaTime

尽管如此,尽管它正在工作,但我并不是 100% 高兴,因为上面发布的代码的输出是“3y 6m 11h”,我不明白这 11 个小时的原因:S 无论如何,我只需要精确所以我相信这不是一个大问题。如果有人知道原因和/或在某些情况下是否有问题,请在评论中告诉我。

【讨论】:

    【解决方案2】:

    您的代码中的句点p 不包含年份或飞蛾,这就是格式化程序根本不输出任何内容的原因。使用格式化程序 PeriodFormat.getDefault(),您会看到它包含小时数,即 30681 = 110451600000 / 1000 / 60 / 60。

    这就是为什么:毫秒可以以定义的方式转换为秒、分钟和小时。但是计算天数、月数或年数是模棱两可的,因为一天中的小时数可能不同(时区偏移),一个月中的天数和一年中的天数也可能不同。见文档:http://joda-time.sourceforge.net/apidocs/org/joda/time/Period.html#Period%28long%29

    在那里找到:

    要更好地控制转换过程,您有两种选择:

    • 将持续时间转换为间隔,并从中获取周期
    • 指定一个周期类型,其中包含精确的日期定义和更大的字段,例如 UTC

    【讨论】:

    • 很好的解释,现在至少我明白了我的代码不起作用的原因,并且非常有意义。另一方面,我完全不清楚如何在做任何有意义的事情方面实现这一点,考虑到我需要转换的时间只是一段时间或持续时间,没有别的。有什么建议吗?非常感谢本杰明。
    • 顺便说一句,在询问之前,我正在尝试使用 PeriodType.YearMonthDay,正如文档所述,但我得到了相同的结果。
    • 嗯,你的问题的实际解决方案取决于你的毫秒数来自哪里。您可以像这样使用实际时间:new Duration(new DateTime(), new DateTime().plus(millis)).toPeriod();,有时可能会导致 3 年零 5 个月,具体取决于代码的执行时间。或者你说毫秒总是“正常”的日子和年份,然后将你的毫秒除以 (1000*60*60*24*365) 并四舍五入到下一个整数。但这相当肮脏。指定相应的时期类型会更好,但我没有这方面的经验。
    • 谢谢本杰明。好吧,我的毫秒数来自一个十进制数,它表示以年为单位的时间量(例如,3.5 年)。我想要做的是以毫秒为单位的年数(3.5 年 = 110376000000 毫秒)转换为进一步的文本格式,如“3 年零 6 个月”。可能我面临一个错误的方法......你怎么看?
    • 我不知道你是否对此有影响,但你可以改变输入年份的方式,这样你就可以分别收到两个整数,而不是小数。如果这不可能,请执行int allMoths = (int) (yearsDecimal * 12); int years = months / 12; int months = allMonths % 12; 之类的操作。但请注意,这可能会导致精度下降(想想 yearsDecimal = 3.14159)。我肯定更喜欢第一个建议。
    猜你喜欢
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-29
    相关资源
    最近更新 更多