【问题标题】:How to get Date object from MONTH("MMMM") or YEAR("yyyy") using DateTimeFormatter如何使用 DateTimeFormatter 从 MONTH("MMMM") 或 YEAR("yyyy") 获取日期对象
【发布时间】:2021-03-25 18:28:42
【问题描述】:

我是使用 DateTimeFormatter 包的新手,我们可以使用 SimpleDateFormat 获得同样的东西。

Date date = new SimpleDateFormat("MMMM").parse(month);//"DECEMBER"
Date date = new SimpleDateFormat("yyyy").parse(year);//"2020"

如何使用 DateTimeFormatter 实现这一点?

【问题讨论】:

  • 哪个月份/格式是MMMM
  • @Naman 无论是使用过时的SimpleDateFormat 还是现代的DateTimeFormatterMMMM 都是完整的月份名称,例如December,而不是例如月份缩写(MMM 代表 Dec)。

标签: java date java-8 simpledateformat datetimeformatter


【解决方案1】:

DateTimeFormatter不支持util.Date类,这里需要使用LocalDate类。你不能只用monthyear解析,你应该传递monthdayyear这3个值来获取日期。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate parsedDate = LocalDate.parse("2020 12 15", formatter);
System.out.print(parsedDate); //2020-12-15

【讨论】:

    【解决方案2】:
        String monthString = "December";
        DateTimeFormatter monthFormatter
                = DateTimeFormatter.ofPattern("MMMM", Locale.ENGLISH);
        Month month = monthFormatter.parse(monthString, Month::from);
        System.out.println(month);
    

    输出:

    十二月

    年份稍微简单一些。我们不需要格式化程序。

        String yearString = "2020";
        Year year = Year.parse(yearString);
        System.out.println(year);
    

    2020

    旧的Date尽管它的名字从未代表日期。这是一个时间点。然而,我们通常将它用于日期、一天中的某个时间、一个月、一年以及更多目的,有时也用于它所在的时间点。一个非常令人困惑的结果是,在极少数情况下,从您的问题中的代码获得的 Date 对象会错误地打印为 11 月而不是 12 月,以及 2019 年而不是 2020 年。您不应再使用 Date 类。它总是设计得很糟糕,而且已经过时了。

    另一方面 java.timeDateTimeFormatter 所属的现代 Java 日期和时间 API,为每个此类概念定义一个类:LocalDate 用于日期,Month一年一个月,Year 一年,等等。它使我们的代码更清楚我们正在处理的内容,这很好。它还要求我们了解不同的类,并考虑每次使用哪一个。

    如果您的月份字符串全部大写,我们需要告诉格式化程序进行解析而不考虑大小写:

        String monthString = "DECEMBER";
        DateTimeFormatter monthFormatter = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .appendPattern("MMMM")
                .toFormatter(Locale.ENGLISH);
        Month month = monthFormatter.parse(monthString, Month::from);
    

    此外,当您的月份名称是英文时,请记住指定英语区域设置。

    【讨论】:

      【解决方案3】:

      检查此链接https://www.baeldung.com/java-datetimeformatter。 您可以使用自定义格式作为

      String europeanDatePattern = "dd.MM.yyyy";
      DateTimeFormatter europeanDateFormatter = DateTimeFormatter.ofPattern(europeanDatePattern);
      System.out.println(europeanDateFormatter.format(LocalDate.of(2016, 7, 31)))
      

      【讨论】:

        【解决方案4】:

        java.util 的日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。让我们看看它们的实际效果:

        import java.text.ParseException;
        import java.text.SimpleDateFormat;
        import java.util.Date;
        
        public class Main {
            public static void main(String[] args) throws ParseException {
                Date date1 = new SimpleDateFormat("MMMM").parse("DECEMBER");
                System.out.println(date1);
                Date date2 = new SimpleDateFormat("yyyy").parse("2020");
                System.out.println(date2);
            }
        }
        

        输出:

        Tue Dec 01 00:00:00 GMT 1970
        Wed Jan 01 00:00:00 GMT 2020
        

        我不需要解释他们采用什么默认值。他们不应该采用这种意外的默认值,而应该发出警报(抛出一些异常),这将有助于程序员做出反应。

        因为这样的意外,建议彻底停止使用,转用modern date-time API

        注意:无论出于何种原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它向后移植了大部分 java.time 功能到 Java 6 和 7。

        如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

        使用现代日期时间 API:

        import java.time.LocalDate;
        import java.time.format.DateTimeFormatter;
        import java.time.format.DateTimeParseException;
        
        public class Main {
            public static void main(String[] args) {
                System.out.println(parse("DECEMBER", "MMMM"));
                System.out.println(parse("2020", "uuuu"));
            }
        
            static LocalDate parse(String text, String pattern) {
                try {
                    return LocalDate.parse(text, DateTimeFormatter.ofPattern(pattern));
                } catch (DateTimeParseException e) {
                    System.out.println(e.getMessage());
                    // Return some default value
                    return LocalDate.MIN;
                }
            }
        }
        

        输出:

        Text 'DECEMBER' could not be parsed at index 0
        -999999999-01-01
        Text '2020' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {Year=2020},ISO of type java.time.format.Parsed
        -999999999-01-01
        

        所以,现在您(程序员)知道您必须做一些事情(例如使用您自己的默认值)来解析字符串。

        演示:

        import java.time.LocalDate;
        import java.time.Month;
        import java.time.Year;
        import java.time.format.DateTimeFormatter;
        import java.time.format.DateTimeFormatterBuilder;
        import java.time.format.DateTimeParseException;
        import java.time.temporal.ChronoField;
        import java.util.Locale;
        
        public class Main {
            public static void main(String[] args) {
                LocalDate date = parse("DECEMBER", "MMMM");
                Month month = parse("DECEMBER", "MMMM").getMonth();
                System.out.println(date);
                System.out.println(month);
        
                date = parse("2020", "uuuu");
                System.out.println(date);
                int year = date.getYear();
                System.out.println(year);
                Year objYear = Year.of(year);
                System.out.println(objYear);
            }
        
            static LocalDate parse(String text, String pattern) {
                LocalDate today = LocalDate.now();
        
                // Formatter using today's day, month and year as defaults
                DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                            .parseCaseInsensitive()
                            .appendPattern(pattern)
                            .parseDefaulting(ChronoField.DAY_OF_MONTH, today.getDayOfMonth())
                            .parseDefaulting(ChronoField.MONTH_OF_YEAR, today.getMonthValue())
                            .parseDefaulting(ChronoField.YEAR, today.getYear())
                            .toFormatter(Locale.ENGLISH);
        
                try {
                    return LocalDate.parse(text, formatter);
                } catch (DateTimeParseException e) {
                    System.out.println(e.getMessage());
                    // Return some default value
                    return LocalDate.MIN;
                }
            }
        }
        

        输出:

        2020-12-15
        DECEMBER
        2020-12-15
        2020
        2020
        

        如果您不想创建日期或日期时间对象,而是只想将字符串解析为MonthYear,则可以通过以下方式进行:

        import java.time.Month;
        import java.time.Year;
        import java.time.format.DateTimeFormatter;
        import java.time.format.DateTimeFormatterBuilder;
        import java.time.format.TextStyle;
        import java.util.Locale;
        
        public class Main {
            public static void main(String[] args) {
                Month month = new DateTimeFormatterBuilder()
                                .parseCaseInsensitive()
                                .appendPattern("MMMM")
                                .toFormatter(Locale.ENGLISH)
                                .parse("DECEMBER", Month::from);
        
                System.out.println(month + " | " + month.getDisplayName(TextStyle.SHORT, Locale.ENGLISH) + " | "
                        + month.getDisplayName(TextStyle.FULL, Locale.ENGLISH));
                
                Year year = DateTimeFormatter.ofPattern("uuuu").parse("2020", Year::from);
                System.out.println(year);
            }
        }
        

        输出:

        DECEMBER | Dec | December
        2020
        

        通过 Trail: Date Time 了解有关现代日期时间 API 的更多信息。

        【讨论】:

          猜你喜欢
          • 2021-01-15
          • 1970-01-01
          • 1970-01-01
          • 2022-06-14
          • 1970-01-01
          • 1970-01-01
          • 2012-03-17
          • 1970-01-01
          • 2014-11-26
          相关资源
          最近更新 更多