Строка карты в другой формат даты - PullRequest
0 голосов
/ 26 апреля 2019

У меня есть требование, при котором я должен отобразить свое значение из входящего запроса как json в Date в любом формате. Например, в моем запросе я могу получить строку даты в любом из следующих форматов:

 1. 03/22/1990 -- MM/dd/yyyy
 2. 03/22/1990 12:34:45 
 3. 03/22/1990 12:23 AM 

Как мне сопоставить значение входящей карты с датой.

Ответы [ 5 ]

2 голосов
/ 26 апреля 2019

Три упомянутых вами формата можно легко идентифицировать с помощью регулярных выражений. Например, шаблон \d\d\/\d\d\/\d\d\d\d \d\d:\d\d:\d\d будет соответствовать второй строке в вашем примере, но не двум другим.

Затем вы можете использовать SimpleDateFormatter с указанным форматом. Э.Г.

SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); 
Date date =formatter1.parse(dateString);
1 голос
/ 26 апреля 2019

Я бы предложил вам использовать библиотеку JodaTime для реализации этой

Вы можете использовать несколько анализаторов и добавлять их в конструктор с помощью метода DateTimeFormatterBuilder.append:

DateTimeParser[] parsers = { 
        DateTimeFormat.forPattern( "MM/dd/yyyy" ).getParser(),
        DateTimeFormat.forPattern( "MM/dd/yyyy HH:mm:ss" ).getParser(),
        DateTimeFormat.forPattern( "MM/dd/yyyy HH:mm tt" ).getParser() 
};
DateTimeFormatter formatter = new DateTimeFormatterBuilder().append( null, parsers ).toFormatter();

DateTime date1 = formatter.parseDateTime( "03/22/1990" );
DateTime date2 = formatter.parseDateTime( "03/22/1990 10:34:11" );
0 голосов
/ 26 апреля 2019

Я думаю, что вам нужно решить две проблемы здесь:

  1. как разобрать даты
  2. как создать собственный десериализатор для вашего JSON

Что касается первой проблемы, вы можете использовать JODA или Java 8. Я остановлюсь на Java 8, потому что новые библиотеки java.time могут обрабатывать форматы в вашем вопросе.

Что касается JSON, я предлагаю использовать библиотеку Джексона, потому что она чрезвычайно гибкая, и вы можете создавать собственные десериализаторы с ее помощью.

Для импорта библиотеки Джексона вы можете использовать следующие зависимости Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.5</version>
</dependency>

Десериализатор по умолчанию должен быть упакован в модуль. Вот пример кода десериализатора:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;

/**
 * Used to deserialize LocalTime from a multiple string formats.
 */
public class GenericDateSerializerModule extends SimpleModule {

    public static final StdScalarDeserializer<LocalDateTime> DATE_TIME_STD_SCALAR_DESERIALIZER =
            new StdScalarDeserializer<LocalDateTime>(LocalDate.class) {

                private DateTimeFormatter[] dtfs =  {
                        new DateTimeFormatterBuilder()
                                .appendPattern("MM/dd/yyyy")
                                .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                                .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                                .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                                .toFormatter(),
                        DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss"),
                        DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a")
                };

                @Override
                public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
                        throws IOException {
                    if (jsonParser.getCurrentTokenId() == JsonTokenId.ID_STRING) {
                        String string = jsonParser.getText().trim();
                        for (DateTimeFormatter dtf : dtfs) {
                            try {
                                return LocalDateTime.parse(string, dtf);
                            } catch(Exception e) {
                                System.err.println(e);
                            }
                        }
                    }
                    return null;
                }
            };

    public GenericDateSerializerModule() {
        addDeserializer(LocalDateTime.class, DATE_TIME_STD_SCALAR_DESERIALIZER);
    }
}

Затем вы можете использовать этот простой модуль с сериализатором для сопоставления JSON с классами:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.time.LocalDateTime;

class GenericDateSerializerModuleTest {

    private ObjectMapper genericDateSerializerMapper = new ObjectMapper();

    @BeforeEach
    void setUp() {
        genericDateSerializerMapper.registerModule(new GenericDateSerializerModule());
    }

    @Test
    void extractMultiFormatDates() throws IOException {
        String json = "{\n" +
                "    \"bookingDate\": \"03/22/1990\",\n" +
                "    \"createdOn\": \"03/22/1990 12:34:45\",\n" +
                "    \"modifiedOn\": \"03/22/1990 12:23 AM\"\n" +
                "}";
        DateJson dateJson = genericDateSerializerMapper.readerFor(DateJson.class).readValue(json);
        System.out.println(dateJson);
    }

    static class DateJson {
        private LocalDateTime BookingDate;
        private LocalDateTime CreatedOn;
        private LocalDateTime ModifiedOn;

        public LocalDateTime getBookingDate() {
            return BookingDate;
        }

        public void setBookingDate(LocalDateTime bookingDate) {
            BookingDate = bookingDate;
        }

        public LocalDateTime getCreatedOn() {
            return CreatedOn;
        }

        public void setCreatedOn(LocalDateTime createdOn) {
            CreatedOn = createdOn;
        }

        public LocalDateTime getModifiedOn() {
            return ModifiedOn;
        }

        public void setModifiedOn(LocalDateTime modifiedOn) {
            ModifiedOn = modifiedOn;
        }

        @Override
        public String toString() {
            return "DateJson{" +
                    "BookingDate=" + BookingDate +
                    ", CreatedOn=" + CreatedOn +
                    ", ModifiedOn=" + ModifiedOn +
                    '}';
        }
    }
}

Если вы запустите этот тест, вы увидите этот вывод на консоли:

java.time.format.DateTimeParseException: Text '03/22/1990 12:34:45' could not be parsed, unparsed text found at index 10
java.time.format.DateTimeParseException: Text '03/22/1990 12:23 AM' could not be parsed, unparsed text found at index 10
java.time.format.DateTimeParseException: Text '03/22/1990 12:23 AM' could not be parsed at index 16
DateJson{BookingDate=1990-03-22T00:00, CreatedOn=1990-03-22T12:34:45, ModifiedOn=1990-03-22T00:23}
0 голосов
/ 26 апреля 2019

Итак, вы можете использовать это одно решение

private Date parse(final String date) {
    return parseDate(date, "MM/dd/yyyy HH:mm a")
        .orElseGet(() -> parseDate(date, "MM/dd/yyyy HH:mm:ss")
            .orElseGet(() -> parseDate(date, "MM/dd/yyyy").orElse(null)));
}

private Optional<Date> parseDate(String date, String pattern) {
    try {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);

        return Optional.of(simpleDateFormat.parse(date));
    } catch (ParseException e) {
        return Optional.empty();
    }
}




 @Test
 public void test() {
    String date = "03/22/1990";
    String date1 = "03/22/1990 12:34:45";
    String date2 = "03/22/1990 12:34 AM";

    System.out.println(parse(date));
    System.out.println(parse(date1));
    System.out.println(parse(date2));
}
0 голосов
/ 26 апреля 2019

Если вам нужно использовать Java.time (по какой-то причине), вы можете использовать что-то вроде этого:

private Timestamp parseDateFromString(String dateString) {
    if (StringUtils.isNotBlank(dateString)) {
        try {
            final DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
            final Date date = df.parse(dateString);
            return new Timestamp(date.getTime());
        } catch (ParseException e) {
            log.error("Error parsing string: " + dateString, e);
        }
    }
    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...