【问题标题】:How to print year sign in DateTimeFormatter when the count of letters is four?当字母数为四个时,如何在 DateTimeFormatter 中打印年号?
【发布时间】:2020-10-25 19:44:20
【问题描述】:

来自DateTimeFormatterjavadoc

如果字母数少于四个(但不是两个),则符号 根据 SignStyle.NORMAL 仅输出负年份。否则, 如果超出焊盘宽度,则输出符号,根据 SignStyle.EXCEEDS_PAD。

据我了解,如果不超过焊盘宽度且字母数为四个,则格式化期间不应打印减号(负年份)。

所以我写了这样一个sn-p的代码(认为我不能使用'y',因为那样年份总是积极的):

    var negativeDate = LocalDate.now().minus(2021, ChronoUnit.YEARS);
    var formatter = DateTimeFormatter.ofPattern("ppppuuuu");
    var text = negativeDate.format(formatter);
    System.out.println("formatted string: " + text);

此代码抛出DateTimeException:“无法打印,因为 5 个字符的输出超过了 4 的填充宽度”。

所以我的问题基本上是如何从 javadoc 工作中看到最后一句话

【问题讨论】:

    标签: java datetime-format java-time datetimeformatter


    【解决方案1】:

    您所问的句子中的否则是指字母数为4或更大的情况。令人困惑的是,这里的 pad 宽度 与用于填充的图案字母 p 无关。它是指要打印的位数。它指回段落的第一句,字母的数量决定了使用填充的最小字段宽度。

    因此,要看到这项工作,请使用 4 个或更多模式字母,并使用位数多于模式字母数的年份。它适用于uyY

        DateTimeFormatter uuuu = DateTimeFormatter.ofPattern("uuuu");
        DateTimeFormatter yyyy = DateTimeFormatter.ofPattern("yyyy");
        DateTimeFormatter uppercaseYyyy = DateTimeFormatter.ofPattern("YYYY");
        
        LocalDate ld = LocalDate.of(12345, Month.OCTOBER, 23);
        
        System.out.println(ld.format(uuuu));
        System.out.println(ld.format(yyyy));
        System.out.println(ld.format(uppercaseYyyy));
    

    输出:

    +12345
    +12345
    +12345
    

    无论要打印的字符数如何,都会打印减号。 SignStyle.EXCEEDS_PAD 的文档说:

    …负值将始终输出'-'符号。

    文档链接: SignStyle.EXCEEDS_PAD

    【讨论】:

      【解决方案2】:

      如果字母数少于四个(但不是两个),则符号 根据 SignStyle.NORMAL 仅输出负年份。

      import java.time.LocalDate;
      import java.time.format.DateTimeFormatter;
      import java.time.temporal.ChronoUnit;
      
      public class Main {
          public static void main(String[] args) {
              var negativeDate = LocalDate.now().minus(2021, ChronoUnit.YEARS);
              var formatter1 = DateTimeFormatter.ofPattern("ppuu");
              var formatter2 = DateTimeFormatter.ofPattern("ppu");
              var text1 = negativeDate.format(formatter1);
              var text2 = negativeDate.format(formatter2);
              System.out.println("formatted string: year" + text1);
              System.out.println("formatted string: year" + text2);
          }
      }
      

      输出:

      formatted string: year01
      formatted string: year-1
      

      我在formatter1 中使用了uu(字母计数为两个),因此它没有显示负号。但是,如果字母数少于四个,而不是两个,则需要提供足够的填充,例如对于这一年,-1,您至少需要填充2(即pp),一个用于- 符号,一个用于1。如果您提供的填充数量较少,您将获得DateTimeException,如果您提供的填充数量多于2,您将在-1 之前获得空间。

      因此,如果格式为uuuu,则负年份需要填充至少5(即ppppp),-4 需要填充年份(0001 ) 即您需要使用DateTimeFormatter.ofPattern("pppppuuuu") 来避免DateTimeException

      【讨论】:

      • 这不能回答我的问题(“如何从 javadoc 工作中看到这最后一句话”) - 所以“否则”的情况下有 4 个字母
      【解决方案3】:

      此模式"ppppuuuu" 定义了padWidth 4 应用于以下格式uuuu,它应用SignStyle.EXCEEDS_PAD(根据javadoc for DateTimeFormatBuilder)。

      也就是说,由于当前的SignStyle- 总是被打印出来。

      因此,当格式化程序尝试打印负年份时,它使用 4 位数字和一个符号,因此超出了可用的 padWidth

      同样,当使用uuuu 模式时,总是会打印该标志,因为在这些情况下会应用SignStyle.NORMAL

      所以,只有在使用uu 格式时才会打印标志。

      为避免出现负数异常,填充应超过位数,例如"ppppu""pppppuuuu"

      var onlyU = DateTimeFormatter.ofPattern("uuuu");
      var padded = DateTimeFormatter.ofPattern("ppppu");
      var padded5 = DateTimeFormatter.ofPattern("pppppuuuu");
      
      for (LocalDate d = LocalDate.now().minus(2421, ChronoUnit.YEARS); d.getYear() < 2200; d = d.plus(400, ChronoUnit.YEARS)) {
      
          try {
              var uuuu  = d.format(onlyU);
              var ppppu = d.format(padded);
              var pppppuuuu = d.format(padded5);
      
              System.out.printf("formatted year=%5d\tuuuu=[%s] \tppppu=[%s]\tpppppuuuu=[%s]%n", d.getYear(), uuuu, ppppu, pppppuuuu);
      
          } catch (DateTimeException e) {
              System.out.println("error: " + e);  
          }
      }
      

      输出:

      formatted year= -401    uuuu=[-0401]    ppppu=[-401]    pppppuuuu=[-0401]
      formatted year=   -1    uuuu=[-0001]    ppppu=[  -1]    pppppuuuu=[-0001]
      formatted year=  399    uuuu=[0399]     ppppu=[ 399]    pppppuuuu=[ 0399]
      formatted year=  799    uuuu=[0799]     ppppu=[ 799]    pppppuuuu=[ 0799]
      formatted year= 1199    uuuu=[1199]     ppppu=[1199]    pppppuuuu=[ 1199]
      formatted year= 1599    uuuu=[1599]     ppppu=[1599]    pppppuuuu=[ 1599]
      formatted year= 1999    uuuu=[1999]     ppppu=[1999]    pppppuuuu=[ 1999]
      

      【讨论】:

      • 谢谢,但您的回答并不能真正解释少于四个和四个或更多字母数量之间的区别(问题中的“否则”)
      • 对不起,我的回答完美地解释了使用ppppuuuu格式时DateTimeException的原因,由于应用了SignStyle.EXCEED_PAD。当前接受的答案不包含任何带有填充的模式。随便...
      • 是的!但请考虑一下我最初的问题是什么!我开始玩这个 p 模式只是因为我误解了最后引用的句子的解释。感谢您的努力,只是这不是我要寻找的东西-这对我来说太复杂了,以至于我什至忘记了我最初的意思:)只有今天的答案才提醒我。也许其他人会发现它很有用。欢呼
      猜你喜欢
      • 2022-12-20
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-05
      • 1970-01-01
      • 2012-03-15
      • 1970-01-01
      相关资源
      最近更新 更多