将大写日期解析为 LocalDate

Posted

技术标签:

【中文标题】将大写日期解析为 LocalDate【英文标题】:Parsing Date in UpperCase to LocalDate 【发布时间】:2019-07-02 13:20:37 【问题描述】:

我正在尝试将字符串 FEBRUARY 2019 解析为 LocalDate

这是我的方法:

LocalDate month = LocalDate.parse("FEBRUARY 2019", DateTimeFormatter.ofPattern("MMMM yyyy"));

或者设置Locale.US:

LocalDate month = LocalDate.parse("FEBRUARY 2019", DateTimeFormatter.ofPattern("MMMM yyyy", Locale.US));

但我得到的只是以下异常:

Exception in thread "main" java.time.format.DateTimeParseException: Text 'FEBRUARY 2019' could not be parsed at index 0

【问题讨论】:

有趣 - 我尝试过使用 DateTimeFormatterBuilder.parseCaseInsensitive(),但这也无济于事:( 即使情况没问题,由于缺少一天部分,仍然会出现错误,请注意。我认为YearMonth 是这里更合适的类型。 【参考方案1】:

首先,我建议您输入的不是日期——它是年份和月份。所以解析到YearMonth,然后根据你的需要创建一个LocalDate。我发现让文本处理代码处理文本处理,并在您已经在日期/时间域中时单独执行任何其他转换是最简单的。

要处理区分大小写的问题,您可以创建一个 DateTimeFormatter 并进行不区分大小写的解析。这是一个完整的例子:

import java.time.*;
import java.time.format.*;
import java.util.*;

public class Test 
    public static void main(String[] args) 
        // Note: this would probably be a field somewhere so you don't need
        // to build it every time.
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .appendPattern("MMMM yyyy")
            .toFormatter(Locale.US);

        YearMonth month = YearMonth.parse("FEBRUARY 2019", formatter);
        System.out.println(month);
    

如果您有不同的表示形式,作为一种替代方法可能有用,您可以构建一个地图并将其传递给DateTimeFormatterBuilder.appendText。 (我只是在不知何故弄乱代码时才发现这一点。)

import java.time.*;
import java.time.format.*;
import java.time.temporal.*;
import java.util.*;

public class Test 
    public static void main(String[] args) 
        // TODO: Build this map up programmatically instead?            
        Map<Long, String> monthNames = new HashMap<>();
        monthNames.put(1L, "JANUARY");
        monthNames.put(2L, "FEBRUARY");
        monthNames.put(3L, "MARCH");
        monthNames.put(4L, "APRIL");
        monthNames.put(5L, "MAY");
        monthNames.put(6L, "JUNE");
        monthNames.put(7L, "JULY");
        monthNames.put(8L, "AUGUST");
        monthNames.put(9L, "SEPTEMBER");
        monthNames.put(10L, "OCTOBER");
        monthNames.put(11L, "NOVEMBER");
        monthNames.put(12L, "DECEMBER");

        // Note: this would probably be a field somewhere so you don't need
        // to build it every time.
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .appendText(ChronoField.MONTH_OF_YEAR, monthNames)
            .appendLiteral(' ')
            .appendPattern("yyyy")
            .toFormatter(Locale.US);

        YearMonth month = YearMonth.parse("FEBRUARY 2019", formatter);
        System.out.println(month);
    

【讨论】:

奇怪,parseCaseInsensitive 似乎对我有用 ideone.com/6GSCog 除非我错过了什么。 @TiiJ7:这很奇怪——它现在也适用于我。现在将编辑代码以显示它。我很想知道我以前做过什么...... @TiiJ7:也编辑了更简单的版本。【参考方案2】:

正如 Jon Skeet 所说,您没有完整的日期来解析并且可以使用 YearMonth。另一种方法是指定默认日期。

除了提供月份名称映射的方法外,您还可以简单地使用 WordUtils 等库将输入转换为正确的格式,例如像这样:

final LocalDate month = LocalDate.parse(
        org.apache.commons.text.WordUtils.capitalizeFully("FEBRUARY 2019"),
        new DateTimeFormatterBuilder()
                    .appendPattern("MMMM uuuu")
                    .parseCaseInsensitive()
                    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
                    .toFormatter(Locale.US));

【讨论】:

给一个月的默认日期也可以,对某些人来说可能是一个很好的解决方案。您需要调用parseCaseInsensitive附加模式以使其生效(因此代码不能按原样工作)。

以上是关于将大写日期解析为 LocalDate的主要内容,如果未能解决你的问题,请参考以下文章

POI设置EXCEL单元格格式为文本小数百分比货币日期科学计数法和中文大写

将带有日期的字符串解析为日期时间对象[重复]

Java将字符串解析为日期返回不正确的日期

如何将日期类转换为正确解析日期时间? [复制]

将 xlsb 文件读取为 pandas 数据框并将日期列解析为日期时间格式

r 将日期/转换字符串解析为日期时间