1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        JDK踩坑: Smart LocalDate

        共 5953字,需瀏覽 12分鐘

         ·

        2021-02-02 00:01

        點(diǎn)擊上方?好好學(xué)java?,選擇?星標(biāo)?公眾號(hào)

        重磅資訊,干貨,第一時(shí)間送達(dá)


        今日推薦:分享一套基于SpringBoot和Vue的企業(yè)級(jí)中后臺(tái)開源項(xiàng)目,這個(gè)項(xiàng)目有點(diǎn)哇塞!

        個(gè)人原創(chuàng)100W +訪問量博客:點(diǎn)擊前往,查看更多

        轉(zhuǎn)自:Telami,

        鏈接:telami.cn/2020/smart_localdate/

        前兩天線上出了個(gè)小問題,有個(gè)統(tǒng)計(jì)頁面報(bào)錯(cuò)了。簡單一看,原來是前端傳了個(gè)無效日期,2020-06-31。


        代碼拋異常在這一行。


        LocalDate.parse(param.getEndDate())


        錯(cuò)誤信息如下:


        java.time.format.DateTimeParseException: Text '2020-06-31' could not be parsed: Invalid date 'JUNE 31'


        先不管為啥前端傳了個(gè)0631,為啥我這轉(zhuǎn)換日期會(huì)報(bào)錯(cuò)呢?已經(jīng)加了校驗(yàn)了啊。


        public static final DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");public static boolean isDateTimeFormat2(String date) {    String regex = "[0-9]{4}-[0-9]{2}-[0-9]{2}";    Pattern pattern = Pattern.compile(regex);    Matcher m = pattern.matcher(date);    boolean dateFlag = m.matches();    if (!dateFlag) {        return false;    } else {        try {            LocalDate.parse(date, dateTimeFormat);            return true;        } catch (DateTimeParseException var6) {            return false;        }    }}


        上面就是校驗(yàn)代碼,用了好久了,debug了一下,發(fā)現(xiàn)確實(shí)校驗(yàn)通過了。



        嗯?等等,我明明傳的【2020-06-31】,怎么變成【2020-06-30】了,咋回事?


        看看源碼吧。


        /** * Obtains an instance of {@code LocalDate} from a text string such as {@code 2007-12-03}. * 

        * The string must represent a valid date and is parsed using * {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE}. * * @param text the text to parse such as "2007-12-03", not null * @return the parsed local date, not null * @throws DateTimeParseException if the text cannot be parsed */public static LocalDate parse(CharSequence text) { return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);}/** * Obtains an instance of {@code LocalDate} from a text string using a specific formatter. *

        * The text is parsed using the formatter, returning a date. * * @param text the text to parse, not null * @param formatter the formatter to use, not null * @return the parsed local date, not null * @throws DateTimeParseException if the text cannot be parsed */public static LocalDate parse(CharSequence text, DateTimeFormatter formatter) { Objects.requireNonNull(formatter, "formatter"); return formatter.parse(text, LocalDate::from);}


        賣關(guān)子好累,不賣了。


        LocalDate.parse 方法有兩個(gè),區(qū)別就是指沒指定 DateTimeFormatter。


        很明顯上面的沒指定,下面那個(gè)指定了。


        /** * Creates a formatter using the specified pattern. * 

        * This method will create a formatter based on a simple * pattern of letters and symbols * as described in the class documentation. * For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'. *

        * The formatter will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}. * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter * Alternatively use the {@link #ofPattern(String, Locale)} variant of this method. *

        * The returned formatter has no override chronology or zone. * It uses {@link ResolverStyle#SMART SMART} resolver style. * * @param pattern the pattern to use, not null * @return the formatter based on the pattern, not null * @throws IllegalArgumentException if the pattern is invalid * @see DateTimeFormatterBuilder#appendPattern(String) */public static DateTimeFormatter ofPattern(String pattern) { return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();}


        劃重點(diǎn):


        It uses {@link ResolverStyle#SMART SMART} resolver style.


        SMART(聰明的,智能的),話說我經(jīng)歷好幾個(gè)叫SMART的項(xiàng)目了……DateTimeFormatter.ofPattern,使用了智能解析模式


        public enum ResolverStyle {    /**     * Style to resolve dates and times strictly.     * 

        * Using strict resolution will ensure that all parsed values are within * the outer range of valid values for the field. Individual fields may * be further processed for strictness. *

        * For example, resolving year-month and day-of-month in the ISO calendar * system using strict mode will ensure that the day-of-month is valid * for the year-month, rejecting invalid values. */ STRICT, /** * Style to resolve dates and times in a smart, or intelligent, manner. *

        * Using smart resolution will perform the sensible default for each * field, which may be the same as strict, the same as lenient, or a third * behavior. Individual fields will interpret this differently. *

        * For example, resolving year-month and day-of-month in the ISO calendar * system using smart mode will ensure that the day-of-month is from * 1 to 31, converting any value beyond the last valid day-of-month to be * the last valid day-of-month. */ SMART, /** * Style to resolve dates and times leniently. *

        * Using lenient resolution will resolve the values in an appropriate * lenient manner. Individual fields will interpret this differently. *

        * For example, lenient mode allows the month in the ISO calendar system * to be outside the range 1 to 12. * For example, month 15 is treated as being 3 months after month 12. */ LENIENT;}


        怎么個(gè)智能法呢?


        1 to 31, converting any value beyond the last valid day-of-month to be the last valid day-of-month.


        超出這個(gè)月的最后有效日,會(huì)被轉(zhuǎn)化為這個(gè)月的最后有效日。就是說 31 就變成 30 了,但是 32 不會(huì),因?yàn)椴辉?1~31 之間。


        現(xiàn)在我們知道了,為啥會(huì)開篇所提的?2020-06-31?會(huì)通過了校驗(yàn),因?yàn)樗?SMART 模式。


        public static final DateTimeFormatter ISO_LOCAL_DATE;static {    ISO_LOCAL_DATE = new DateTimeFormatterBuilder()            .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)            .appendLiteral('-')            .appendValue(MONTH_OF_YEAR, 2)            .appendLiteral('-')            .appendValue(DAY_OF_MONTH, 2)            .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);}


        而沒指定 DateTimeFormatter 的,則使用了默認(rèn)的 ISO_LOCAL_DATE??梢钥闯?,它使用了 ResolverStyle.STRICT,嚴(yán)格模式。


        到這里,就是全部真相了,看來JDK Smart與否,還得看使用者啊。

        推薦文章

        原創(chuàng)電子書

        歷時(shí)整整一年總結(jié)的?Java面試+ Java入門技術(shù)學(xué)習(xí)指南,這是本人這幾年及校招的總結(jié),各種異步面試題已經(jīng)全部進(jìn)行總結(jié),按照章節(jié)復(fù)習(xí)即可,已經(jīng)拿到了了大廠提供。

        原創(chuàng)思維導(dǎo)圖

        掃碼或者微信搜?程序員的技術(shù)圈子?回復(fù)?面試?領(lǐng)取原創(chuàng)電子書和思維導(dǎo)圖。

        瀏覽 62
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            久久久久激情电影 | 啊别了快cao我啊~网站 | 羞羞视频免费app国产 | 中国黄片免费 | 国内黄片| 成人天堂一级婬片A片AAA软件 | 老司机午夜激情 | 少妇菊爆视频在线播放 | 天天爽夜夜欢 | 男女啪啪啪网站免费 |