如何 使用 Java 8 时间 API 将 两位 数 年份 转换 为 完整 年份

qojgxg4l  于 2022-11-20  发布在  Java
关注(0)|答案(5)|浏览(185)

我 希望 从 项目 中 删除 Joda-Time 库 。
我 正在 尝试 将 两位 数 的 年份 转换 为 完整 的 年份 。 Joda-Time 中 的 以下 代码 可以 实现 此 目的 。 下面 是 Joda-time 的 以下 代码

DateTimeFormatter TWO_YEAR_FORMATTER = DateTimeFormat.forPattern("yy");
int year = LocalDate.parse("99"", TWO_YEAR_FORMATTER).getYear();
System.out.println(year);

中 的 每 一 个
产量 : 1999 年
这 是 我 所 期望 的 输出 , 在 我 的 情况 下 也 是 有 意义 的 。 但是 , 当 我 用 java.time API 尝试 相同 的 过程 时 , 它 产生 了 一 个 DatetimeParseException 。 下面 是 java.time API 的 以下 代码 :

DateTimeFormatter TWO_YEAR_FORMATTER = DateTimeFormatter.ofPattern("yy");
int year = LocalDate.parse("99", TWO_YEAR_FORMATTER).getYear();
System.out.println(year);

格式

    • 堆栈 跟踪 : * *
Exception in thread "main" java.time.format.DateTimeParseException: Text '99' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {Year=2099},ISO of type java.time.format.Parsed
    at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
    at java.base/java.time.LocalDate.parse(LocalDate.java:428)
    at scratch.main(scratch.java:10)
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {Year=2099},ISO of type java.time.format.Parsed
    at java.base/java.time.LocalDate.from(LocalDate.java:396)
    at java.base/java.time.format.Parsed.query(Parsed.java:235)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    ... 2 more

格式
我 没有 看到 堆栈 跟踪 的 原因 。 如果 有人 能 帮助 我 理解 下面 的 场景 , 并 解释 如何 使用 Java 8 时间 API 将 两位 数 的 年份 转换 为 完整 的 年份 , 那 就 太 好 了 。

m3eecexj

m3eecexj1#

问题是你不能把年份本身解析成LocalDate,LocalDate需要更多的信息。
您可以使用格式化程序的parse方法,该方法将为您提供一个TemporalAccessor,然后从中获取year字段:

int year = TWO_YEAR_FORMATTER.parse("99").get(ChronoField.YEAR);
System.out.println(year);

解决两者之间的差异:这是两个不同的API。是的,它们非常相似,并且java.time包是由JodaTime的设计决策决定的,但它从未打算成为JodaTime的直接替代品。
如果要更改透视年,请参阅此答案(默认情况下,“99”将解析为2099而不是1999)。

fhity93d

fhity93d2#

为什么不起作用
java.time不像Joda-Time那样提供月份和日期的默认值。
该消息指出,它无法仅从年份中获取LocalDate,或者相反,它缺少月份和日期(不过,您可以提供自己的默认值,如Mikhail Kholodkov’s answer中所示)。
一般来说,这种行为是为了帮助我们:它提醒我们提供所有需要的值,并从代码中清楚地表明是否使用了任何默认值,以及使用了哪些默认值。

该怎么做

只需使用java.timeYear类。

public static final DateTimeFormatter TWO_YEAR_FORMATTER = new DateTimeFormatterBuilder()
        .appendValueReduced(ChronoField.YEAR, 2, 2, 1950)
        .toFormatter();

然后使用

int year = Year.parse("99", TWO_YEAR_FORMATTER).getValue();
System.out.println(year);

输出量
1999
在1950处插入所需的基准值,以指定从该年起99年(含)内的年份。如果希望年份是过去的年份(包括今年),可以用途:

private static final Year base = Year.now(ZoneId.of("Asia/Kolkata")).minusYears(99);
public static final DateTimeFormatter TWO_YEAR_FORMATTER = new DateTimeFormatterBuilder()
        .appendValueReduced(ChronoField.YEAR, 2, 2, base.getValue())
        .toFormatter();

顺便说一句,不要相信我的话,但我认为Joda-Time使用当前年份减去30年作为基数或枢轴。如果是这样,在最后一个片段中使用30而不是99将是最兼容的(所以也会给予你你所期望的1999)。

nmpmafwu

nmpmafwu3#

您无法创建LocalDate,因为您给予的String未提供填写所有必填字段所需的信息。
但是,您可以创建一个Year

Year parsed = Year.parse("99", TWO_YEAR_FORMATTER);
int year = parsed.getValue();
mqxuamgl

mqxuamgl4#

您需要提供DAY_OF_MONTHMONTH_OF_YEAR的默认值

DateTimeFormatter TWO_YEAR_FORMATTER = new DateTimeFormatterBuilder()
                .appendPattern("yy")
                .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
                .toFormatter();

此外,在本发明的实施例中,
Java-8默认使用2000-2099的范围,而不是像SimpleDateFormat那样使用相对于今天的-80年到+20年的范围。
Full answer
因为您只解析年份,所以要将'99'作为'1999',您的代码应该如下所示:

DateTimeFormatter TWO_YEAR_FORMATTER = new DateTimeFormatterBuilder()
                .appendPattern("")
                .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
                .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
                .appendValueReduced(ChronoField.YEAR_OF_ERA, 2, 2, LocalDate.now().minusYears(80))
                .toFormatter();
pb3skfrl

pb3skfrl5#

您可以使用formatter.parse(input, Year::from)直接解析年份:

import java.time.*;
import java.time.format.*;
class Main {
  public static void main(String[] args) {
    DateTimeFormatter TWO_YEAR_FORMATTER = DateTimeFormatter.ofPattern("yy");
    Year year = TWO_YEAR_FORMATTER.parse("99", Year::from);
    System.out.println(year);
  }
}

注意,这将输出2099。要输出1999,您应该使用特定的格式化程序,如the one suggested by Ole V.V. in their answer

相关问题