jdk8中新增的java.time包真的是不要太棒,jdk8以前的date存在着线程不安全、api难用等问题。来看看新的date有些什么特点:
1、使用不可变对象保证线程安全
LocalDateTime中有两个final修饰的成员,date表示日期(年月日部分),time表示时间(时分秒部分)。
/**
* The date part.
*/
private final LocalDate date;
/**
* The time part.
*/
private final LocalTime time;
LocalDate中直接使用year、month、day三个成员变量表示年月日,LocalTime中使用hour、minute、second、nano表示时分秒和纳秒。底层源码看起来很清晰易懂。
对LocalDateTime对象的任何修改操作都会生成一个新的实例返回,也就是说LocalDateTime对象本身一旦生成是不可变的。多线程操作中也无需考虑线程安全问题,因为本身API层面就不支持修改。
2、新老API实现时间的加减运算
使用旧的API实现在当前时间上加一个小时的操作:
@Test
public void testDate(){
Date date = new Date();
System.out.println(date);
date.setHours(date.getHours()+1);
System.out.println(date);
}
java.util.Date的setHours和getHours方法已经过去,推荐使用Calendar
@Test
public void testDate2(){
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.HOUR_OF_DAY, 1);
System.out.println(calendar.getTime());
}
使用LocalDateTime
@Test
public void test1(){
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.toString());
LocalDateTime localDateTime2= localDateTime.plusHours(1L);
System.out.println(localDateTime2.toString());
}
个人觉得使用Calendar需要了解Calendar和Date的关系,了解其add方法的用法,使用LocalDateTime直接根据方法名就知道是干嘛的,更不用说字符串和Date互转有多麻烦了。以前一直不懂为啥对Date的操作还要通过Calendar去完成,LocalDateTime的设计更加符合单一职责的原则,更加符合使用习惯。
3、需要注意的地方
3.1、LocalDateTime的toString方法并不是标准的时间格式的输出
貌似很正常,再看一个正好秒为0的
秒不见了,不是标准的格式哟。
同样有个格式化的工具DateTimeFormatter
3.2、转json字符串时需要配置序列化工具
测试jackson和fastjson两种方式:
@Test
public void testParseJson() throws JsonProcessingException {
LocalTimeDateTestDto localTimeDateTestDto = new LocalTimeDateTestDto(LocalDateTime.now());
//jackson方式转换
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("jackson方式转换: "+objectMapper.writeValueAsString(localTimeDateTestDto));
//fastjson方式转换
System.out.println("fastjson方式转换: " + JSON.toJSONString(localTimeDateTestDto));
}
@Data
@AllArgsConstructor
class LocalTimeDateTestDto{
private LocalDateTime time;
}
结果
jackson方式转换: {"time":{"year":2020,"month":"MARCH","nano":537000000,"monthValue":3,"dayOfMonth":30,"hour":20,"minute":49,"second":3,"dayOfYear":90,"dayOfWeek":"MONDAY","chronology":{"id":"ISO","calendarType":"iso8601"}}}
fastjson方式转换: {"time":"2020-03-30T20:49:03.537"}
fastjson还是能正常转换的,jackson就离我们的预想差得有点儿远了。
再看字符串转Object,fastjson使用字符串{“time”:“2020-03-30T20:49:03.537”}还是可以成功转为LocalTimeDateTestDto的。
最后,修复jackson方式还是有办法的:
改造LocalTimeDateTestDto,配置jackson的序列化工具和反序列化工具,还可使用@JsonFormat指定特定的格式
@Data
@NoArgsConstructor
@AllArgsConstructor
public class LocalTimeDateTestDto{
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime time;
}
再测试对象转字符串
字符串转Object