为什么使用JDK8的时间
好用!
好用!
好用!
高大上,线程安全,计算方便等一些列的好处,你什么不使用它
JDK8时间
编号 | 类的名称 | 描述 |
---|---|---|
1 | Instant | 时间戳 |
2 | Duration | 持续时间,时间差 |
3 | LocalDate | 只包含日期,比如:2018-02-05 |
4 | LocalTime | 只包含时间,比如:23:12:10 |
5 | LocalDateTime | 包含日期和时间,比如:2018-02-05 23:14:21 |
6 | Period | 时间段 |
7 | ZoneOffset | 时区偏移量,比如:+8:00 |
8 | ZonedDateTime | 带时区的时间 |
9 | Clock | 时钟,比如获取目前美国纽约的时间 |
10 | java.time.format.DateTimeformaer | 时间格式化 |
e.g. 1. Java 8中处理特定日期
我们通过静态工厂方法now()非常容易地创建了当天日期,你还可以调用另一个有用的工厂方法LocalDate.of()创建任意日期, 该方法需要传入年、月、日做参数,返回对应的LocalDate实例。这个方法的好处是没再犯老API的设计错误,比如年度起始于1900,月份是从0开 始等等。
import java.time.LocalDate;
public class Demo03 {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2018,2,6);
System.out.println("自定义日期:"+date);
}
}
e.g. 2. Java 8中检查像生日这种周期性事件
import java.time.LocalDate;
import java.time.MonthDay;
public class Demo05 {
public static void main(String[] args) {
LocalDate date1 = LocalDate.now();
LocalDate date2 = LocalDate.of(2018,2,6);
MonthDay birthday = MonthDay.of(date2.getMonth(),date2.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(date1);
if(currentMonthDay.equals(birthday)){
System.out.println("是你的生日");
}else{
System.out.println("你的生日还没有到");
}
}
}
只要当天的日期和生日匹配,无论是哪一年都会打印出祝贺信息。你可以把程序整合进系统时钟,看看生日时是否会受到提醒,或者写一个单元测试来检测代码是否运行正确。
e.g. 3. Java 8的Clock时钟类
Java 8增加了一个Clock时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。以前用到System.currentTimeInMillis()和TimeZone.getDefault()的地方都可用Clock替换。
import java.time.Clock;
public class Demo10 {
public static void main(String[] args) {
// Returns the current time based on your system clock and set to UTC.
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock.millis());
// Returns time based on system clock zone
Clock defaultClock = Clock.systemDefaultZone();
System.out.println("Clock : " + defaultClock.millis());
}
}
e.g. 4. Java 8中处理时区
Java 8不仅分离了日期和时间,也把时区分离出来了。现在有一系列单独的类如ZoneId来处理特定时区,ZoneDateTime类来表示某时区下的时间。这在Java 8以前都是 GregorianCalendar类来做的。下面这个例子展示了如何把本时区的时间转换成另一个时区的时间。
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Demo12 {
public static void main(String[] args) {
// Date and time with timezone in Java 8
ZoneId america = ZoneId.of("America/New_York");
LocalDateTime localtDateAndTime = LocalDateTime.now();
ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localtDateAndTime, america );
System.out.println("Current date and time in a particular timezone : " + dateAndTimeInNewYork);
}
}
e.g. 5. 如何表示信用卡到期这类固定日期,答案就在YearMonth
与 MonthDay检查重复事件的例子相似,YearMonth是另一个组合类,用于表示信用卡到期日、FD到期日、期货期权到期日等。还可以用这个类得到 当月共有多少天,YearMonth实例的lengthOfMonth()方法可以返回当月的天数,在判断2月有28天还是29天时非常有用。
import java.time.*;
public class Demo13 {
public static void main(String[] args) {
YearMonth currentYearMonth = YearMonth.now();
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2019, Month.FEBRUARY);
System.out.printf("Your credit card expires on %s %n", creditCardExpiry);
}
}
e.g. 6. 如何在Java 8中检查闰年
import java.time.LocalDate;
public class Demo14 {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
if(today.isLeapYear()){
System.out.println("This year is Leap year");
}else {
System.out.println("2018 is not a Leap year");
}
}
}
e.g. 7. 计算两个日期之间的天数和月数
有一个常见日期操作是计算两个日期之间的天数、周数或月数。在Java 8中可以用java.time.Period类来做计算。
下面这个例子中,我们计算了当天和将来某一天之间的月数。
import java.time.LocalDate;
import java.time.Period;
public class Demo15 {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate java8Release = LocalDate.of(2018, 12, 14);
Period periodToNextJavaRelease = Period.between(today, java8Release);
System.out.println("Months left between today and Java 8 release : "
+ periodToNextJavaRelease.getMonths() );
}
}
e.g. 8. 在Java 8中获取当前的时间戳
Instant类有一个静态工厂方法now()会返回当前的时间戳,如下所示:
import java.time.Instant;
public class Demo16 {
public static void main(String[] args) {
Instant timestamp = Instant.now();
System.out.println("What is value of this instant " + timestamp.toEpochMilli());
}
}
时间戳信息里同时包含了日期和时间,这和java.util.Date很像。实际上Instant类确实等同于 Java 8之前的Date类,你可以使用Date类和Instant类各自的转换方法互相转换,例如:Date.from(Instant) 将Instant转换成java.util.Date,Date.toInstant()则是将Date类转换成Instant类。
e.g. 9. Java 8中如何使用预定义的格式化工具去解析或格式化日期
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Demo17 {
public static void main(String[] args) {
String dayAfterTommorrow = "20180205";
LocalDate formatted = LocalDate.parse(dayAfterTommorrow,
DateTimeFormatter.BASIC_ISO_DATE);
System.out.println(dayAfterTommorrow+" 格式化后的日期为: "+formatted);
}
}
e.g. 10. 字符串互转日期类型
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Demo18 {
public static void main(String[] args) {
LocalDateTime date = LocalDateTime.now();
DateTimeFormatter format1 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//日期转字符串
String str = date.format(format1);
System.out.println("日期转换为字符串:"+str);
DateTimeFormatter format2 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//字符串转日期
LocalDate date2 = LocalDate.parse(str,format2);
System.out.println("日期类型:"+date2);
}
}
LocalDateTime基础
时间类
LocalDate yyyy-MM-dd
LocalTime HH:mm:ss
LocalDateTime yyyy-MM-dd HH:mm:ss
时间格式
常见的格式是:
yyyy-MM-dd HH:mm:ss
对应结果
2018-01-23 15:02:43
一般情况如上,那么有些特殊的地方用到特殊的用法,记不住备用以后查看
/**
日期格式化类(必须掌握)
API:
G Era 标志符 Text AD
y 年 Year 1996; 96
M 年中的月份 Month July; Jul; 07
w 年中的周数 Number 27
W 月份中的周数 Number 2
D 年中的天数 Number 189
d 月份中的天数 Number 10
F 月份中的星期 Number 2
E 星期中的天数 Text Tuesday; Tue
a Am/pm 标记 Text PM
H 一天中的小时数(0-23) Number 0
k 一天中的小时数(1-24) Number 24
K am/pm 中的小时数(0-11) Number 0
h am/pm 中的小时数(1-12) Number 12
m 小时中的分钟数 Number 30
s 分钟中的秒数 Number 55
S 毫秒数 Number 978
z 时区 General time zone Pacific Standard Time; PST; GMT-08:00
Z 时区 RFC 822 time zone -0800
*/
yyyy-MM-dd E a HH:mm:ss
2018-01-23 星期二 下午 15:05:27
LocalDateTime时间转换
Spring MVC
Form表单请求 格式化时间
Form表单请求指的是,以QueryString方式传递参数或者Form-Data传递时的请求
- 字符串转LocalDateTime
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- Long转LocalDateTime
增加一个Converter
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* @author wangqimeng
* @date 2020/1/13 14:52
*/
@Component
public class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
@Override
public LocalDateTime convert(String source) {
if (!NumberUtils.isDigits(source)) {
return null;
}
Long milli = NumberUtils.createLong(source);
return LocalDateTime.ofEpochSecond(milli, 0, ZoneOffset.UTC);
}
}
注意 上下两种方式不能兼容使用 Convert级别高
Json 格式化时间
Json解析前提
maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
or 已经有jackson 缺少
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
相关基础注解
基础注解
@DateTimeFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ss.SSS")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ss.SSS")
描述:
关于Long与LocalDateTime相互转换
- Long转LocalDateTime
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
/**
* @author <a href="mailto:boommanpro@gmail.com">boommanpro</a>
* @date 2019/7/19 14:20
*/
public class Long2LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String time=jsonParser.getText();
Instant instant = Instant.ofEpochMilli(Long.parseLong(time));
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
}
}
- LocalDateTime2Long
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
/**
* @author <a href="mailto:boommanpro@gmail.com">boommanpro</a>
* @date 2019/7/19 14:20
*/
public class LocalDateTime2LongSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeNumber(String.valueOf(value.toInstant(ZoneOffset.of("+8")).toEpochMilli()));
}
}
Spring Date Jpa
Jpa语法查询
JPA可以根据你写的一个函数名来生成对应的SQL语句,当然函数名是要符合特定规则的。
这里介绍between和in的用法
@Query(nativeQuery = true,
value = "select * from z_cashier_data" +
"where abstract_code = ?1 " +
"and time BETWEEN ?2 and ?3")
Page<CashierData> findAllabcd(String code, LocalDateTime start, LocalDateTime end, Pageable pageable);//函数名随意
相当于下面这条
Page<CashierData> findAllByAbstractCodeAndTimeBetween(String code, LocalDateTime start, LocalDateTime end, Pageable pageable);
Specification语法
LocalDateTime start, LocalDateTime end
criteriaBuilder.between(root.get("workDay"),start,end)
Es LocalDateTime 相关注解
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
@Field(index = false, type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")