【问题标题】:Joda-Time: Formatting with multiple formats with single FormatterJoda-Time:使用单个 Formatter 进行多种格式格式化
【发布时间】:2011-07-13 11:57:43
【问题描述】:

我想打印以毫秒为单位的持续时间,并根据其大小使用不同的格式规范:

case (1)      "H:mm"  if duration < 10 hours
case (2)     "HH:mm"  if duration < 24 hours
case (3)  "#d HH:mm"  else (duration >= 24 hours)

这意味着持续时间低于 10 小时时只有 1 小时字段数字,
但如果有前导日字段,则为 2 小时字段数字!

例子:

case (1)      "0:45"  means 45 minutes,
              "1:23"  means 1 hour and 23 minutes,
case (2)     "12:05"  means 12 hours and 5 minutes and
case (3)  "1d 05:09"  means 1 day, 5 hours and 9 minutes
                               (= 29 hours and 9 minutes).

我试过了

object JodaTest {
  import org.joda.time._
  private val pdf = {
    import format._
    val pfb = new PeriodFormatterBuilder()
      .appendDays.appendSeparator("d ")
      .printZeroAlways
      .minimumPrintedDigits(2).appendHours.appendSeparator(":")
      .appendMinutes
    new PeriodFormatter(pfb.toPrinter, null)
  }
  def durstr(duration: Long): String =
    pdf.print((new Period(duration)).normalizedStandard)
}

导致

  2700000 => "00:45"     but should be "0:45"
  4980000 => "01:23"     but should be "1:23"
 43500000 => "12:05"
104940000 => "1d 05:09"

但我不知道如何在情况 (1) 中省略两位数日表示的前导零 但同时在具有相同 PeriodFormat 的情况下 (3) 强制打印它。

是否可以使用单个 org.joda.time.format.PeriodFormatter 来做到这一点?

【问题讨论】:

  • 一开始不是minimumPrintedDigits(1),在几分钟工作之前不是minimumPrintedDigits(2)吗?
  • @Daniel 认为 minimumPrintedDigits(1) 是默认值(可以省略),但我已经尝试过,它在前两种情况下工作正常,但在情况 (3) 中它留给@987654328 @ 而需要104940000 =&gt; "1d 05:09"。 - P.S.: ...我的输入键有问题;-)
  • 啊,我明白了……嗯,它几乎做到了。 :-)
  • @Daniel 感谢您的评论,我在答案中也发现了案例 (3) 中的一个错误,并按照您的建议对测试套件进行了修改并通过插入 .minimumPrintedDigits(2).appendMinutes 来修复它。

标签: java scala formatting jodatime duration


【解决方案1】:

也许不是一个真正的答案,但同时我担心你需要 两个 PeriodFormatter 来解决这个任务,所以管理它

object JodaTest {
  import org.joda.time._
  import format._
  private def pdf(digits: Int) = new PeriodFormatter(
    new PeriodFormatterBuilder()
      .appendDays.appendSeparator("d ")
      .printZeroAlways
      .minimumPrintedDigits(digits).appendHours.appendSeparator(":")
      .minimumPrintedDigits(2).appendMinutes
      .toPrinter, null)
  private lazy val pdf1 = pdf(1)
  private lazy val pdf2 = pdf(2)
  def durstr(duration: Long): String = {
    val period = new Period(duration).normalizedStandard
    val pdf = if (period.getDays > 0) pdf2 else pdf1
    pdf.print(period)
  }
}

导致想要的

  2700000 => "0:45"
  4980000 => "1:23"
 43500000 => "12:05"
104940000 => "1d 05:09".

【讨论】:

    【解决方案2】:

    仍然找到了一个只有 一个 PeriodFormatter 的解决方案,但在 Joda-Time 之外做了一些工作。

    这个想法是

    1. 使用 Joda-Time 生成原始格式化字符串,如“000d 00:00”和
    2. 分别删除不需要的前导零

    object JodaTest {
      import org.joda.time._
      import format._
      // "000d 00:00" - 3 day digits for periods with up to 999 days long
      private val pdf = new PeriodFormatter(new PeriodFormatterBuilder()
        .printZeroAlways
        .minimumPrintedDigits(3).appendDays.appendSeparator("d ")
        .minimumPrintedDigits(2).appendHours.appendSeparator(":").appendMinutes
        .toPrinter, null)
      private def adjust(rawstr: String): String = {
        // "000d 00:00" => ("000d 0", "0:00")
        val (first, second) = rawstr splitAt 6
        // remove unwanted leading zeros in first part, keep it in second
        first.dropWhile(c => !c.isDigit || c == '0') + second
      }
      def durstr(duration: Long): String = {
        // PeriodType.dayTime => day is the most significant field (no weeks etc.)
        adjust(pdf.print(new Period(duration) normalizedStandard PeriodType.dayTime))
      }
    }
    

    导致

       duration =>       rawstr =>       adjust
              0 => "000d 00:00" =>       "0:00"
        2700000 => "000d 00:45" =>       "0:45"
        4980000 => "000d 01:23" =>       "1:23"
       43500000 => "000d 12:05" =>      "12:05"
      104940000 => "001d 05:09" =>   "1d 05:09"
      518760000 => "006d 00:06" =>   "6d 00:06"
      605220000 => "007d 00:07" =>   "7d 00:07"
      951060000 => "011d 00:11" =>  "11d 00:11"
    43230000000 => "500d 08:20" => "500d 08:20"
    

    当然,最好直接使用 Joda-Time 构建此类格式,方法是指定 Excel 数字格式 (#,##0.00#) 之类的模式来说明在哪里需要零或仅在需要时使用。但似乎不清楚如何准确定义它,因为您不仅有 '0' 和 '#',而且每个字段都需要字符并将文字放入格式字符串(可能通过转义)也会很好。

    【讨论】:

      【解决方案3】:

      您可以实现PeriodPrinter 接口以完全按照您的意愿格式化句点,然后使用the builder 设置格式化程序。

      【讨论】:

      • 我会深入了解PeriodPrinter界面,稍后再回复。
      • 好的,通过实现PeriodPrinter 接口并使用构建器构建它,我可以获得一个回答我的问题的任意PeriodFormatter =>。
      猜你喜欢
      • 2011-03-19
      • 2017-01-11
      • 2013-08-17
      • 2021-03-22
      • 2023-04-09
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 2015-01-24
      相关资源
      最近更新 更多