代码之家  ›  专栏  ›  技术社区  ›  Angelina

检查字符串并处理无效日期

  •  3
  • Angelina  · 技术社区  · 6 年前

    当我遇到无效日期时,即 2018-02-31, 2018-11-31 ,我希望我的代码将其转换为当月的最后一天。

    我不知道如何检查传递的字符串中的值。

    以下是迄今为止我的代码:

    /**
         * If date comes back as invalid, i.e. 2018-11-31
         * convert it to have last day of given month.
         *  
         * @param nextFieldTypeDate
         * @return
         */
        public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
            LocalDate convertedDate = null;
            try {
                convertedDate = LocalDate.parse(nextFieldTypeDate);
            } catch(DateTimeException dte) {
                //convertedDate = convert date to have last day of the month
                DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM");
                String yearMonthString = nextFieldTypeDate.subSequence(0, 7).toString();
                YearMonth ym = YearMonth.parse(yearMonthString, fmt);
                convertedDate = ym.atEndOfMonth();
            } catch(Exception e) {
                logger.error(e.getMessage());
                throw new ConversionException("Unable to convert nextFieldTypeDate.", e);
            }
            return convertedDate;
        }
    
    2 回复  |  直到 6 年前
        1
  •  4
  •   Anonymous    6 年前

    这个 parseUnresolved A方法 DatetimeFormatter 解析而不尝试理解解析的值。因此,它接受一个无效的日期,并允许您在尝试创建一个 LocalDate 离开他们。

    public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
        ParsePosition position = new ParsePosition(0);
        TemporalAccessor parsed = DateTimeFormatter.ISO_LOCAL_DATE
                .parseUnresolved(nextFieldTypeDate, position);
        if (position.getIndex() < nextFieldTypeDate.length()) {
            throw new IllegalArgumentException("Could not parse entire string");
        }
        YearMonth ym = YearMonth.from(parsed);
        int lastDayOfMonth = ym.lengthOfMonth();
        int parsedDayOfMOnth = parsed.get(ChronoField.DAY_OF_MONTH);
        if (parsedDayOfMOnth > lastDayOfMonth) { // invalid, must be adjusted to lasst day of month
            return ym.atEndOfMonth();
        } else {
            return ym.atDay(parsedDayOfMOnth);
        }
    }
    

    让我们试试这个版本的方法:

        System.out.println(resolveInvalidDate("2018-02-31"));
        System.out.println(resolveInvalidDate("2018-02-27"));
    

    输出为:

    2018-02-28
    2018-02-27
    

    因此2月31日无效,已调整为2月28日,2018年为该月的最后一天。2月27日有效,原样退回。

    编辑: 为了一个相关的目的,人们可能会认为 DateTimeFormatter.ISO_LOCAL_DATE.withResolverStyle(ResolverStyle.LENIENT).parse(nextFieldTypeDate, LocalDate::from) . 然而,这反过来了 2018-02-31 进入之内 2018-03-03 我知道这不是你想要的。

        2
  •  1
  •   Garikai    6 年前

    不是最干净的解决方案,但这应该有效:

    public static LocalDate resolveInvalidDate(String nextFieldTypeDate) {
            LocalDate convertedDate = null;
            try {
                convertedDate = LocalDate.parse(nextFieldTypeDate);
            } catch(DateTimeException dte) {
                //convertedDate = convert date to have last day of the month
                Integer[] constituents = Arrays.stream(nextFieldTypeDate.split("-"))
                                               .map(constituentString -> Integer.valueOf(constituentString))
                                               .toArray(Integer::new);
                LocalDate defaultDate = LocalDate.of(constituents[0], constituents[1], 1);
                LocalDate convertedDate = LocalDate.of(defaultDate.getYear(), defaultDate.getMonth(), defaultDate.lengthOfMonth());
            } catch(Exception e) {
                logger.error(e.getMessage());
                throw new ConversionException("Unable to convert nextFieldTypeDate.", e);
            }
            return convertedDate;
        }