做网站和做app哪个简单,微信推广文案范文,天津建设银行官方网站,网站设计怎么做一点首页就跳转1 SimpleDateFormat 之坑1.1 格式化1.1.1 案例初始化一个Calendar#xff0c;设置日期2020年12月29日日志这是由于混淆SimpleDateFormat的各种格式化模式#xff1a;小写y是年大写Y是week year#xff0c;即所在的周属于哪一年一年第一周的判断方式从getFirstDayOfWeek(…1 SimpleDateFormat 之坑1.1 格式化1.1.1 案例初始化一个Calendar设置日期2020年12月29日日志这是由于混淆SimpleDateFormat的各种格式化模式小写y是年大写Y是week year即所在的周属于哪一年一年第一周的判断方式从getFirstDayOfWeek()开始完整的7天并且包含那一年至少getMinimalDaysInFirstWeek()天。该计算方式和区域相关对zh_CN区域2020年第一周条件从周日开始的完整7天2020年包含1天即 可。显然2019年12月27日周日到2020年1月2日周六是2020年第一周得出的week year就是2021年。若把区域改为法国Locale.setDefault(Locale.FRANCE);则week yeay就还是2020年因为一周的第一天从周一开始算2020年的第一周是2019年12月28日周一开始27日还是属于去年小结无特殊需求针对年份的日期格式化应该一律使用 “y” 而非 “Y”。线程安全问题使用一个100线程的线程池循环20次把时间格式化任务提交到线程池处理每个任务中又循环10次解析2020-01-01 11:12:13这样一个时间表示运行程序后大量报错即使没有报错的输出结果也不正常比如2020年解析成57728年SimpleDateFormat 用于定义解析和格式化日期时间的模式。看起来是一次性工作应该复用但它的解析和格式化操作都非线程安全。分析源码SimpleDateFormat继承自DateFormatDateFormat有字段CalendarSimpleDateFormat#parse调用CalendarBuilder#establish构建Calendarestablish方法内部先清空Calendar再构建Calendar整个操作没有加锁。显然若使用线程池调用parse即多线程并发操作一个Calendar就可能会产生一个线程还没来得及处理Calendar就被另一个线程清空。format方法同理不再赘述。因此只能在同一个线程复用SimpleDateFormat解决方案通过ThreadLocal来存放SimpleDateFormat日志输出全部正确1.2 当需要解析的字符串和格式不匹配SimpleDateFormat还是能得到结果案例使用yyyyMM解析20160901字符串居然输出2112年这是因为把 1111当成月份对于SimpleDateFormat的这些坑使用Java 8中的DateTimeFormatter即可避免。2 Java 8中的DateTimeFormatter2.1 格式化字符串首先使用DateTimeFormatterBuilder定义格式化字符串无需死记大写Y还是小写y大写M还是小写m2.2 线程安全可定义为static使用2.3 待解析字符串和格式不匹配时就报错日志2020/11/11 11:11:11.789 Exception in thread main java.time.format.DateTimeParseException: Text 20201111 could not be parsed at index 0 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777) at org.javaedge.time.commonmistakes.datetime.dateformat.CommonMistakesApplication.better(CommonMistakesApplication.java:96) at org.javaedge.time.commonmistakes.datetime.dateformat.CommonMistakesApplication.main(CommonMistakesApplication.java:47)3 Java8计算日期时间有人喜欢使用时间戳进行计算比如希望得到当前时间后30天:把new Date().getTime得到的时间戳加30天对应毫秒数得到的日期居然比当前日期还要早根本不是后30天因为int发生了溢出。应将30改为30L使其为long正确输出Java 8前代码建议使用Calendar使用Java 8的日期时间类型可以直接进行各种计算更加简洁和方便对日期时间做计算操作日期时间API会比Calendar功能强大很多。3.1 minus/plus直接对日期加减3.2 with快捷时间调节TemporalAdjusters.firstDayOfMonth得到当前月的第一天TemporalAdjusters.firstDayOfYear()得到当前年的第一天TemporalAdjusters.previous(DayOfWeek.SATURDAY)得到上一个周六TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)得到本月最后一个周五3.3 使用lambda自定义的时间调整为当前时间增加100天以内的随机天数判断日期是否符合某个条件query查询是否匹配条件使用Java 8操作和计算日期时间虽然方便但计算两个日期差时可能会踩坑Java 8中有一个专门的类Period定义了日期间隔通过Period.between得到了两个LocalDate的差返回的是两个日期差几年零几月零几天。如果希望得知两个日期之间差几天直接调用Period的getDays()方法得到的只是最后的“零几天”而不是算总的间隔天数。比如计算2020年12月12日和2020年10月1日的日期间隔很明显日期差是2个月零11天但获取getDays方法得到的结果只是11天而不是72天可使用ChronoUnit.DAYS.between解决这个问题4 总结也许你认为java.util.Date类似于新API中的LocalDateTime。其实不是虽然它们都没时区概念java.util.Date类是因为使用UTC表示所以没有时区概念其本质是时间戳LocalDateTime严格上可以认为是一个日期时间的表示而不是一个时间点因此在把Date转换为LocalDateTime的时候需要通过Date的toInstant方法得到一个UTC时间戳进行转换并需要提供当前的时区这样才能把UTC时间转换为本地日期时间的表示。反过来把LocalDateTime的时间表示转换为Date时也需要提供时区用于指定是哪个时区的时间表示也就是先通过atZone方法把LocalDateTime转换为ZonedDateTime然后才能获得UTC时间戳Date in new Date(); LocalDateTime ldt LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault()); Date out Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());有人说新API很麻烦还需要考虑时区真麻烦。但并非因为API强行设计繁琐而是UTC时间要变为当地时间必须考虑时区---------------------为什么阿里巴巴的程序员成长速度这么快霸榜GitHub的Offer来了原理篇框架篇开放分享50W年薪程序员需要的技术栈分析看完三件事❤️如果你觉得这篇内容对你还蛮有帮助我想邀请你帮我三个小忙点赞转发有你们的 『点赞和评论』才是我创造的动力。关注公众号 『 Java斗帝 』不定期分享原创知识。同时可以期待后续文章ing