<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          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)開(kāi)源項(xiàng)目,這個(gè)項(xiàng)目有點(diǎn)哇塞!

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

          轉(zhuǎn)自:Telami,

          鏈接:telami.cn/2020/smart_localdate/

          前兩天線上出了個(gè)小問(wèn)題,有個(gè)統(tǒng)計(jì)頁(yè)面報(bào)錯(cuò)了。簡(jiǎn)單一看,原來(lái)是前端傳了個(gè)無(wú)效日期,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)通過(guò)了。



          嗯?等等,我明明傳的【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ū)別就是指沒(méi)指定 DateTimeFormatter。


          很明顯上面的沒(méi)指定,下面那個(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(聰明的,智能的),話說(shuō)我經(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è)月的最后有效日。就是說(shuō) 31 就變成 30 了,但是 32 不會(huì),因?yàn)椴辉?1~31 之間。


          現(xiàn)在我們知道了,為啥會(huì)開(kāi)篇所提的?2020-06-31?會(huì)通過(guò)了校驗(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);}


          而沒(méi)指定 DateTimeFormatter 的,則使用了默認(rèn)的 ISO_LOCAL_DATE。可以看出,它使用了 ResolverStyle.STRICT,嚴(yán)格模式。


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

          推薦文章

          原創(chuàng)電子書(shū)

          歷時(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)電子書(shū)和思維導(dǎo)圖。

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费观看国产一卡二卡电影 | 免费视频在线观看黄 | 黄色片在线视频 | 在线观看豆花 | 800av在线播放 |