最近做了很多统计方面的功能,基本是要和日期这个东西打交道,各种,前移多少天,前移几个小时,前移几分钟的操作,虽然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语句,(不会写存储过程或者函数,也没有功夫探索了)
复制代码