Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > DateFormat Странная работа или так положено?


Автор: Mirkes 19.6.2014, 00:04
День добрый.
Столкнулся с несколько странной проблемой. Клиент предоставил базу данных, в которой дата записана мало того, что в текстовом виде, так еще и в нескольких вариантах.
Заготовил для всех вариантов форматы
Код

    private static DateFormat df2 = new SimpleDateFormat("dd/MM/yy");
    private static DateFormat df4 = new SimpleDateFormat("dd/MM/yyyy");
    private static DateFormat df4f = new SimpleDateFormat("dd MMM yyyy");
    private static DateFormat dfin = new SimpleDateFormat("yyyyMMdd");
    private static DateFormat dfinv = new SimpleDateFormat("yyyy-MM-dd");
    private static DateFormat df4t = new SimpleDateFormat("dd/MM/yyyy HH:mm");
    private static DateFormat dfb = new SimpleDateFormat("dd MMM yyyy HH:mm");
    private static DateFormat dft = new SimpleDateFormat("HH:mm");
    private static DateFormat dft1 = new SimpleDateFormat("HHmm");


И далее в нужном месте разбираю (знаю, что не блестящий вариант, но пока устраивает).
Код

                Date d;
                try {
                    d = df4.parse(arg);
                } catch (ParseException e2) {
                    try {
                        d = df2.parse(arg);
                    } catch (ParseException e3) {
                        try {
                            d = dfb.parse(arg);
                        } catch (ParseException e4) {
                            try {
                                d = df4f.parse(arg);
                            } catch (ParseException e5) {
                                try {
                                    d = df4t.parse(arg);
                                } catch (ParseException e6) {
                                    try {
                                        d = dfinv.parse(arg);
                                    } catch (ParseException e7) {
                                        try {
                                            d = dfin.parse(arg);
                                        } catch (ParseException e8) {
                                            return new String[0];
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return new String[] { df4.format(d) };



Формат "yyyy-MM-dd" добавился последним. (новая версия базы - новые форматы smile
Далее налетел на проблему: форматы df4, df2, dfb, df4f, df4t как и ожидалось не могли прочитать дату 2012-03-18. А вот формат dfin смог, но не правильно - получилось 03.12.2011. В приведенном выше тексте я уже переставил два последних формата и это решило проблему. Осталось только недоумение, как формату dfin удалось прочитать текст не подходящий по структуре? Этот ошибка или так и должно быть?

Автор: LSD 20.6.2014, 11:39
В твем конкретном случае, поможет setLenient(false), но там есть еще одна проблема, парсер не требует точного соответсвия, т.е. строка "2012-03-18 abc" будет распарсена. Вот пример как с этим бороться:
Код

    private static final TimeZone         UTC         = TimeZone.getTimeZone("UTC");
    private static final DateFormat       DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
    private static final List<String>     formats     = asList("dd/MM/yy",
                                                               "dd/MM/yyyy",
                                                               "dd MMM yyyy",
                                                               "yyyyMMdd",
                                                               "yyyy-MM-dd",
                                                               "dd/MM/yyyy HH:mm",
                                                               "dd MMM yyyy HH:mm",
                                                               "HH:mm",
                                                               "HHmm");
    private static final List<DateFormat> dateFormats = formats.stream()
                                                               .map(s -> {
                                                                   DateFormat dateFormat = new SimpleDateFormat(s);
                                                                   dateFormat.setLenient(false);
                                                                   dateFormat.setTimeZone(UTC);
                                                                   return dateFormat;
                                                               })
                                                               .collect(Collectors.toList());

    private static void exec() throws Exception {
        DATE_FORMAT.setTimeZone(UTC);

        asList("2012-03-18",
               "2012-03-18 abc").stream()
                                .collect(Collectors.toMap(Function.identity(), App::parse))
                                .forEach(App::test);
    }

    public static void test(String string, Optional<Date> date) {
        logger.info("'{}' => {}", string, date.flatMap(d -> Optional.of(DATE_FORMAT.format(d))).orElse("unparseable"));
    }

    public static Optional<Date> parse(String date) {
        date = date.trim();
        for (DateFormat format : dateFormats) {
            ParsePosition position = new ParsePosition(0);
            Date parsedDate = format.parse(date, position);
            if (parsedDate != null && position.getIndex() == date.length()) {
                return Optional.of(parsedDate);
            }
        }
        return Optional.empty();
    }

на фишки Java 8 не обращай внимание, самое главное в том как создается SimpleDateFormat и parse().

Автор: Mirkes 20.6.2014, 11:45
Спасибо! Буду разбираться!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)