十年的 Joda DateTimeFormat

问题描述

我想以 yDDD 格式格式化 Joda LocalDateTime,其中“y”代表的不是全年,而是一位代表十年中的一年,而 DDD 代表一年中的某一天。似乎“yDDD”作为格式字符串正确地将 DDD 解释为“一年中的某一天”,但不是打印年份的单个字符,而是打印整个 4 位数字的年份。如何仅使用年份的最后一位数字来格式化 Joda LocalDateTime?

例如,2021 年 2 月 1 日将表示为 1032:

  • 1 表示十年中的第 1 年
  • 032 表示一年中的第 32 天。

解决方法

这是使用java date api,但它应该很容易转移到joda:

std::function<>

它产生:

@Test
public void testDateFormat() {
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("DDD");
    ZonedDateTime date = ZonedDateTime.now();
    System.out.println("formatted: " + (date.getYear() % 10) + date.format(fmt));
}
,

java.time 和 DateTimeFormatterBuilder.appendValueReduced()

据我所知,Joda-Time 不能做你想做的事。 java.time 是自 Java 8 以来取代 Joda-Time 的现代 Java 日期和时间 API,可以。通过这个格式化程序:

private static final DateTimeFormatter ydddFormatter = new DateTimeFormatterBuilder()
        .appendValueReduced(ChronoField.YEAR,1,LocalDate.of(2020,Month.JANUARY,1))
        .appendPattern("DDD")
        .toFormatter();

演示:

    LocalDate sampleDate = LocalDate.of(2021,Month.FEBRUARY,1);
    String formattedDate = sampleDate.format(ydddFormatter);
    System.out.println(formattedDate);

输出:

1032

appendValueReduced 方法专门用于打印和解析 2 位数年份,但我们也没有理由不能将它用于 1 位数年份。对于固定宽度的 1 位数年份字段,只需为 widthmaxWidth 传递 1。

appendValueReduced 的最后一个参数,即我代码中的 LocalDate,是解析时用于解释 1 位数年份的基准日期。对于格式化,它被忽略,但它仍然需要存在。

Joda-Time 和 String.format()

如果您的日期必须来自 Joda-Time 并且您现在没有升级,则在格式化时您需要使用 Joda-Time 以外的其他方式(就像其他答案一样)。我对简单解决方案的建议是在 String.format() 上全押:

    LocalDateTime dateTime = new LocalDateTime(2021,2,23,45);
    String ydddString = String.format(Locale.US,"%01d%03d",dateTime.getYear() % 10,dateTime.getDayOfYear());
    assert ydddString.length() == 4 : ydddString;
    System.out.println(ydddString);

1032

,

java.time

Joda-Time 项目现在处于维护模式。它的创建者 Stephen Colebourne 继续创建了它的替代品,Java 8 及更高版本中内置的 java.time 类。

我没有找到只使用格式化程序对象来做您想做的事情的方法。然而,Ole V.V.确实在 this other Answer 中找到了方法。我推荐该解决方案。

在我的方法中,编写一个方法来进行一些字符串操作,或者使用 Answer by Erik 中显示的数学。

    LocalDate ld = LocalDate.of( 2021,1 ) ;
    String yyyy = Integer.toString( ld.getYear() ) ;  // Get the number of the year as text.
    String y = yyyy.substring( yyyy.length() - 1 ) ;  // Pull last character of that year-as-text to get single-digit year of decade.
 
    DateTimeFormatter f = DateTimeFormatter.ofPattern( "DDD" ) ;  // Get day-of-year,1-365 or 1-366. 
    String output = y + ld.format( f ) ;

    System.out.println( output ) ;

看到这个code run live at IdeOne.com

1001

ISO 8601

我建议坚持使用 ISO 8601 中定义的标准格式:四位数年份、连字符、三位数年份。

因此,2021-01-01 是 2021-001

LocalDate.now().format( DateTimeFormatter.ISO_ORDINAL_DATE )