最近做了很多统计方面的功能,基本是要和日期这个东西打交道,各种,前移多少天,前移几个小时,前移几分钟的操作,虽然Java的Calendar这个日历操作类能搞定,但是还是感觉写起来有点费劲.果不其然,让我发现了LocalDate LocalTime LocalDateTime这个JAVA8新增的时间类
java.util.Date和java.sql.Date是jdk1就开始提供了,java.sql.Date继承了java.util.Date,我们和数据库交互,一般是采用java.util.Date这个类,因为java.sql.Date的getHours,getMinutes,gitSeconds这三个方法都是这么写的:
@Deprecated public int getHours() { throw new java.lang.IllegalArgumentException(); } @Deprecated public int getMinutes() { throw new java.lang.IllegalArgumentException(); } @Deprecated public int getSeconds() { throw new java.lang.IllegalArgumentException(); } 对应的setXXXX方法也是如出一辙的抛出IllegalArgumentException异常 例如: @Deprecated public void setHours(int i) { throw new java.lang.IllegalArgumentException(); } 并且还带有@Deprecated(废弃)这个注解,看来,java.sql.Date只能显示到:年月日这个级别了,也就是:2019-11-22这种形式的数据 复制代码
LocalDate,LocalTime,LocalDateTIme这三个类是java8新提供的时间操作类,在java.time包下面.这三个类是从org.joda.time吸收过来的(地方武装的工具类被提成标准部队了). 1.LocalDate是主管:yyyy-MM-dd(2019-11-22)这种形式,也就是只管:年-月-日 2.LocalTime是主管:HH:mm:ss (14:56:23)这种形式,也就是只管:时:分:秒 3.LocalDateTime是主管:yyyy-MM-dd HH:mm:ss 这种形式,也就是只管:年-月-日 时:分:秒(LocalDateTime是由LocalDate和LocalTime组成的) 复制代码
LocalDate,LocaTime,LocalDateTime提供了基本上一致,有以下集中: now()系列: //默认时区 public static LocalDate now() { return now(Clock.systemDefaultZone()); } //自定义时区,例如你可以通过ZoneId.of("America/New_York")使用纽约的时区 public static LocalDate now(ZoneId zone) { return now(Clock.system(zone)); } //自定义时钟,这个有点高深,还没使用过 public static LocalDate now(Clock clock) { Objects.requireNonNull(clock, "clock"); // inline to avoid creating object and Instant checks final Instant now = clock.instant(); // called once ZoneOffset offset = clock.getZone().getRules().getOffset(now); long epochSec = now.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY); return LocalDate.ofEpochDay(epochDay); } of系列:(这里只列举LocalDate的of) //根据年月日构造LocalDate对象,这个地方的dayOfMonth是1-31的取值 public static LocalDate of(int year, Month month, int dayOfMonth) { YEAR.checkValidValue(year); Objects.requireNonNull(month, "month"); DAY_OF_MONTH.checkValidValue(dayOfMonth); return create(year, month.getValue(), dayOfMonth); } //同上,只是都是使用int类型来传递参数了 public static LocalDate of(int year, int month, int dayOfMonth) { YEAR.checkValidValue(year); MONTH_OF_YEAR.checkValidValue(month); DAY_OF_MONTH.checkValidValue(dayOfMonth); return create(year, month, dayOfMonth); } //这个是定位到一年当中的第几天 public static LocalDate ofYearDay(int year, int dayOfYear) { YEAR.checkValidValue(year); DAY_OF_YEAR.checkValidValue(dayOfYear); boolean leap = IsoChronology.INSTANCE.isLeapYear(year); if (dayOfYear == 366 && leap == false) { throw new DateTimeException("Invalid date 'DayOfYear 366' as '" + year + "' is not a leap year"); } Month moy = Month.of((dayOfYear - 1) / 31 + 1); int monthEnd = moy.firstDayOfYear(leap) + moy.length(leap) - 1; if (dayOfYear > monthEnd) { moy = moy.plus(1); } int dom = dayOfYear - moy.firstDayOfYear(leap) + 1; return new LocalDate(year, moy.getValue(), dom); } 复制代码
获取现在的时间对象:
//时间是:2019-11-22 LocaDate now = LocalDate.now(); //时间是:14:43:56 LocalTime now = LocalTime.now(); //时间是:2019-11-22 14:43:56 LocalDateTime now = LocalDateTime.now(); 复制代码
使用of来具体定制时间
//时间是:2015-12-20 LocalDate localDate = LocalDate.of(2015,12,20); //时间是:15:36:48 LocalTime localTime = LocalTime.of(15,36,48); //时间是:2013-09-21 05:56:24 LocalDateTime localDateTime = LocalDateTime.of(2013,9,21,5,58,24); 复制代码
各种条件的定位时间
老铁们一定要注意:凡是LocalDate各种操作之后,他都返回一个新的LocalDate对象,所以,你要接着这个新对象啊,你要是不用对象接着,那么就会看到不起作用,这样子好链式编程
我们在开发中可能遇到各种条件的定位时间:本月的第一天,本月的最后一天,本月每周的周一,本月每周的周三,本年度的第9月的第二天,或者哪一年的上述各种情况: //我们随便拿个时间做实验,以求做到一般化处理,就拿2019-10-22日来处理吧 LocalDate localDate = LocalDate.of(2019,10,22); //**老铁们一定要注意:凡是LocalDate各种操作之后,他都返回一个新的LocalDate对象,所以,你要接着这个新对象啊,你要是不用对象接着,那么就会看到不起作用,这样子好链式编程** //1.获取本月的第一天,输出:2019-10-01 localDate = localDate.with(TemporalAdjusters.firstDayOfMonth()) //2.获取本月的最后一天,输出:2019-10-31 localDate = localDate.with(TemporalAdjusters.lastDayOfMonth()); //3.本年第一天,输出:2019-01-01 localDate = localDate.with(TemporalAdjusters.firstDayOfYear()); //4.本年最后一天,输出:2019-12-31 localDate = localDate.with(TemporalAdjusters.lastDayOfYear()); //5.下一个周几的操作,输出:2019-10-24 //注意,2019-10-22是周二,所以下一个周四就是2019-10-24,如果是下一个周一,那就是:2019-10-28了 //当然也有对应的previes方法,就是上一个周几 localDate = localDate.with(TemporalAdjusters.next(DayOfWeek.THURSDAY)); localDate = localDate.with(TemporalAdjusters.previes(DayOfWeek.THURSDAY)); //6.本月第2周的周五,输出是:2019-10-11 localDate = localDate.with(TemporalAdjusters.dayOfWeekInMonth(2,DayOfWeek.FRIDAY)); //7.还有下一个月的第一天,输出是:2019-11-01,当然还有下一年 localDate = localDate.with(TemporalAdjusters.firstDayOfNextMonth()); //8.加一天,输出是:2019-10-23 localDate = localDate.plusDays(1L); //9.加一周,输出是:2019-10-29(即使是跨年和跨月,也会正确加的,不用担心) localDate = localDate.plusWeeks(1L); //10.加一个月,输出是:2019-11-22(下一月没有31号这种情况,他们会帮我们处理的),例如:2019-10-31加一个月,返回:2019-11-30(放心,JDK都是进过各种验证的,不会出现人不能理解的错误的) localDate = localDate.plusMonths(1L); 复制代码
这个之前比较时间都是getTime然后比较一下就行,现在LocalDate,LocalTime,LocalDateTime提供了isBefore,isAfter方法
LocalDate first = LocalDate.now(); LocalDate second = LocalDate.of(2015,12,25); first.isBefore(second);//返回:false first.isAfter(second);//返回:true 复制代码
我们避免不了经常需要格式化日期字符串,这方面Local系列做的也很好
//输出为:2019-10-22 localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); 不用像之前还要一个SimpleDateFormatter了 复制代码
5.扯到最后,有点不适应,就是java.util.Date和LocalDate,LocalTime,LocalDateTime没有直接互转的方法,没办法,自己补充一个了
//java.util.Date类型转LocalDateTime public static LocalDateTime dateToLocalDateTime(Date date) { Instant instant = date.toInstant(); ZoneId zoneId = ZoneId.systemDefault(); return instant.atZone(zoneId).toLocalDateTime(); } //java.time.LocalDateTime转java.util.Date public static Date localDateTimeToDate(LocalDateTime localDateTime) { ZoneId zoneId = ZoneId.systemDefault(); ZonedDateTime zdt = localDateTime.atZone(zoneId); return Date.from(zdt.toInstant()); } 有了LocalDateTime,你就可以操作获取LocalDate,LocalTime了,当然也有转Date<-->LocalDate Date<-->LocalTime的操作, 在这个地方就不一一列举了!,其实就是instant.atZone(zoneId).toLocalDateTime()修改这句话就行 复制代码
String sqlFormat = "drop table gsms_phone_detection_0101"; LocalDate startDate = LocalDate.of(2012, 1, 1); LocalDate endDate = LocalDate.of(2012, 12, 31); List<String> result = Stream.iterate(startDate, localDate -> localDate.plusDays(1L)) .limit(ChronoUnit.DAYS.between(startDate, endDate) + 1) .map(localDate -> localDate.format(DateTimeFormatter.ofPattern("MMdd"))) .map(tableSuffix -> sqlFormat.replaceAll("0101",tableSuffix)) .collect(Collectors.toList()); Files.write(Paths.get("/home/liuxu/Pictures/gsms_ded_red_det_verify_xxxx.sql"),result); 这是我生成删除按照日分表的sql语句,(不会写存储过程或者函数,也没有功夫探索了) 复制代码