在 JodaTime 中将持续时间转换为字符串

Convert duration to String in JodaTime

我有一个持续时间,例如像这样:

PT-27900S = -27900000 milliseconds

我想将其转换为格式为 (+/-HH:mm) 的字符串 我将负持续时间转换为字符串:

final PeriodFormatter hoursAndMinutesFormatter = new PeriodFormatterBuilder()
                                                .printZeroAlways()
                                                .minimumPrintedDigits(2)
                                                .appendHours()
                                                .appendSeparator(":")
                                                .appendMinutes()
                                                .toFormatter();

我明白了这个结果:

-07:-45

但我想要这样。

-07:45

是否可以这样格式化?

好吧,Joda-Time 中不支持您想要查看负持续时间的方式 。每个文档(由名称表示)我能看到的最接近的可能是方法 rejectSignedValues()。我已经在每个可能的配置中测试了它(在开始时插入它,直接在 appendMinutes() 之前,直接在后面,在所有情况下都使用未记录的参数 falsetrue),但它没有在我的测试中做任何事情(见更新 side-note)。

所以逻辑上只剩下两个选项:

a) 编写此技巧:

PeriodFormatter hoursAndMinutesFormatter = new PeriodFormatterBuilder()
.printZeroAlways()
.minimumPrintedDigits(2)
.appendHours()
.appendSeparator(":")
//.rejectSignedValues(true) // no effect ?!
.appendMinutes()
.toFormatter();     

long millis = -27900000;
Duration d =  new Duration(millis);
Period p = d.toPeriod();
String s;
if (millis < 0) {
    s = "-" + hoursAndMinutesFormatter.print(p.negated());
} else {
    s = hoursAndMinutesFormatter.print(p);
}

System.out.println("Joda-Time: " + s); // -07:45

b) 或者切换到另一个对负持续时间有更好支持的库。

=> built-in XML-duration 的示例,它具有更好的符号处理,但除了 XML-Schema 兼容表示之外没有真正的格式化程序(尽管你是可以自由查询持续时间的单个组成部分并使用 java.util.Formatter).

对其进行格式化
long millis = -27900000;
javax.xml.datatype.Duration xmlDuration = 
    DatatypeFactory.newInstance().newDuration(millis);
System.out.println("XML: " + xmlDuration.toString()); // -P0Y0M0DT7H45M0.000S
System.out.println(
    String.format(
        "%1$s%2d:%3d", 
        xmlDuration.getSign() < 0 ? "-" : "+", 
        xmlDuration.getHours(), 
        xmlDuration.getMinutes())); // -07:45

=> 或者使用我的库 Time4J which has a pattern-based duration formatter:

long millis = -27900000;
Duration<ClockUnit> duration = Duration.of(millis, ClockUnit.MILLIS); // create
duration = duration.with(Duration.STD_CLOCK_PERIOD); // normalization to hours and minutes
String s = Duration.formatter("-hh:mm").format(duration);
System.out.println("Time4J: " + s); // -07:45

旁注:

  1. 新的 Java-8 类 DurationPeriod 具有与 Joda-Time 相同的符号处理(不喜欢符号在前面但在每个组件之前)。当你观察方法 toString() 的输出时你可以看到它。不提供任何特殊的持续时间格式化程序。

  2. Joda-Time 的符号处理与 XML-Schema v1.1 不兼容(请特别查看部分:3.3.6.2 词法映射)。

  3. 现在我知道了方法rejectSignedValues()是干什么用的了。它是相关的 for parsing only 并且只控制异常行为(可通过其布尔参数配置)。但是,解析像“-07:45”这样的值会产生与您的输入不同的意外 millis-value (-22500000 != -27900000).