Как получить объект Date из MONTH ("MMMM") или YEAR ("yyyy") с помощью DateTimeFormatter

Я новичок в использовании пакета DateTimeFormatter, и то же самое мы можем получить, используя SimpleDateFormat.

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

Как добиться этого с помощью DateTimeFormatter?

какой месяц/формат MMMM?

Naman 15.12.2020 09:42

@Naman Независимо от того, используете ли вы устаревшее SimpleDateFormat или современное DateTimeFormatter, MMMM означает полное название месяца, например. December, в отличие, например, от аббревиатуры месяца (MMM вместо Dec).

Ole V.V. 15.12.2020 20:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
2
577
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

проверьте эту ссылку 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)))

DateTimeFormatter не поддерживает класс util.Date, здесь вам нужно использовать класс LocalDate. Вы не можете анализировать только с помощью month или year, вы должны передать 3 значения month, day и year, чтобы получить дату.

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
LocalDate parsedDate = LocalDate.parse("2020 12 15", formatter);
System.out.print(parsedDate); //2020-12-15
    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, полученные из кода в вашем вопросе, в редких случаях неправильно печатались как ноябрь вместо декабря и как 2019 вместо 2020 года. Вам больше не следует использовать класс Date. Он всегда был плохо спроектирован и давно устарел.

С другой стороны, java.time, современный API даты и времени Java, к которому принадлежит DateTimeFormatter, определяет класс для каждого такого понятия: LocalDate для даты, Month для месяца года, Year для года и т. д. Это делает наш код дает более четкое представление о том, с чем мы имеем дело, и это хорошо. Это также требует, чтобы мы узнали о различных классах и думали о том, какой из них использовать каждый раз.

Если ваша строка месяца была написана заглавными буквами, нам нужно указать программе форматирования выполнять синтаксический анализ без учета регистра:

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

Также, если название месяца указано на английском языке, не забудьте указать англоязычную локаль.

Ответ принят как подходящий

API даты и времени java.util и их 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

Мне не нужно объяснять, какие значения по умолчанию они принимают. Вместо того, чтобы принимать такие неожиданные значения по умолчанию, они должны были поднять тревогу (сгенерировать какое-то исключение), на которую программисту было бы полезно среагировать.

Из-за таких неожиданностей рекомендуется полностью прекратить их использование и перейти на современный API даты и времени.

Примечание. По какой-либо причине, если вам нужно придерживаться Java 6 или Java 7, вы можете использовать ThreeTen-Backport, который переносит большую часть функций java.time на Java 6 и 7.

Если вы работаете над проектом Android и ваш уровень Android API по-прежнему не соответствует Java-8, проверьте API Java 8+, доступные через дешугаринг и Как использовать ThreeTenABP в 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

Если вы не хотите создавать объект даты или даты и времени, а хотите просто разобрать строку на Month и Year, вы можете сделать это следующим образом:

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

Узнайте больше о современном API даты и времени на Trail: Date Time.

Другие вопросы по теме