首页 > 解决方案 > 如何在 Java DateTime API 中解析带有日本数字的日期字符串

问题描述

在询问[如何将日本时代的日期字符串值解析为 LocalDate & LocalDateTime ]后,
我对以下案例感到好奇;

明治二十三年十一月二十九日

有没有办法将日本日历字符(本质上是日本日期)上的日本数字解析为? 仅使用 Java DateTime API。我不想修改输入字符串值,但只希望 API 来处理识别。LocalDate

标签: javadatetimejava-8internationalizationdatetime-format

解决方案


对于任何阅读的人,您的示例日期字符串包含一个时代指示符,23 年的时代(在这种情况下对应于公元 1890 年公历),第 11 个月和第 29 个月的日期。月份和日期与公历中的相同。

由于日语数字不完全是位置的(例如阿拉伯数字),因此 aDateTimeFormatter不会自行解析它们。因此,我们通过提供数字在日语(和中文)中的外观来帮助它。DateTimeFormatterBuilder有一个重载appendText方法,它接受一个将所有可能的数字作为文本保存的地图。我的代码示例不完整,但应该可以帮助您入门。

    Locale japaneseJapan = Locale.forLanguageTag("ja-JP");

    Map<Long, String> numbers = Map.ofEntries(
            Map.entry(1L, "\u4e00"),
            Map.entry(2L, "\u4e8c"),
            Map.entry(3L, "\u4e09"),
            Map.entry(4L, "\u56db"),
            Map.entry(5L, "\u4e94"),
            Map.entry(6L, "\u516d"),
            Map.entry(7L, "\u4e03"),
            Map.entry(8L, "\u516b"),
            Map.entry(9L, "\u4e5d"),
            Map.entry(10L, "\u5341"),
            Map.entry(11L, "\u5341\u4e00"),
            Map.entry(12L, "\u5341\u4e8c"),
            Map.entry(13L, "\u5341\u4e09"),
            Map.entry(14L, "\u5341\u56db"),
            Map.entry(15L, "\u5341\u4e94"),
            Map.entry(16L, "\u5341\u516d"),
            Map.entry(17L, "\u5341\u4e03"),
            Map.entry(18L, "\u5341\u516b"),
            Map.entry(19L, "\u5341\u4e5d"),
            Map.entry(20L, "\u4e8c\u5341"),
            Map.entry(21L, "\u4e8c\u5341\u4e00"),
            Map.entry(22L, "\u4e8c\u5341\u4e8c"),
            Map.entry(23L, "\u4e8c\u5341\u4e09"),
            Map.entry(24L, "\u4e8c\u5341\u56db"),
            Map.entry(25L, "\u4e8c\u5341\u4e94"),
            Map.entry(26L, "\u4e8c\u5341\u516d"),
            Map.entry(27L, "\u4e8c\u5341\u4e03"),
            Map.entry(28L, "\u4e8c\u5341\u516b"),
            Map.entry(29L, "\u4e8c\u5341\u4e5d"),
            Map.entry(30L, "\u4e09\u4e8c\u5341"));

    DateTimeFormatter japaneseformatter = new DateTimeFormatterBuilder()
            .appendPattern("GGGG")
            .appendText(ChronoField.YEAR_OF_ERA, numbers)
            .appendLiteral('\u5e74')
            .appendText(ChronoField.MONTH_OF_YEAR, numbers)
            .appendLiteral('\u6708')
            .appendText(ChronoField.DAY_OF_MONTH, numbers)
            .appendLiteral('\u65e5')
            .toFormatter(japaneseJapan)
            .withChronology(JapaneseChronology.INSTANCE);

    String dateString = "明治二十三年十一月二十九日";
    System.out.println(dateString + " is parsed into " + LocalDate.parse(dateString, japaneseformatter));

此示例的输出为:

明治二十三年十一月二十九日被解析为1890-11-29

假设一个时代可能超过 30 年,您需要为地图提供更多数字。你可以比我做得更好(也可以检查我的号码是否有错误)。使用几个嵌套循环来填充地图可能是最好的(不太容易出错),但我不确定我能不能正确地做到这一点,所以我把这部分留给你。

今天我学到了一些关于日本数字的东西。

我使用的一些链接


推荐阅读