java 8新特性 instant 和 LocalDateTime

一直都知道SimpleDateFormat是线程不安全的,现在还是出现了问题。阿里Java规范中(六.5)有这么一条强制

 

Instant
 java.time 包中的 Instant 类代表的是某个时间(有点像 java.util.Date),准确的说是:”是不带时区的即时时间点“,它是精确到纳秒的(而不是象旧版本的Date精确到毫秒)。如果使用纳秒去表示一个时间则原来使用一位Long类型是不够的,需要占用更多一点的存储空间,实际上其内部是由两个Long字段组成,第一个部分保存的是自标准Java计算时代(就是1970年1月1日开始)到现在的秒数,第二部分保存的是纳秒数(永远不会超过999,999,999)。

实例代码如下:

 1 // DateTimeFormatter - SimpleDateFormat
 2 // Intant - Date
 3 // LocalDateTime - Calendar
 4  
 5 // date与instant的相互转化
 6 Instant now = Instant.now();
 7 Date date = Date.from(now);
 8 Instant instant = date.toInstant();
 9 // LocalDateTime代替Calendar
10 ZoneId zoneId = ZoneId.systemDefault();
11 LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
12 int year = localDateTime.getYear();
13 int month = localDateTime.getMonthValue();
14 int dayOfMonth = localDateTime.getDayOfMonth();
15 int hour = localDateTime.getHour();
16 int minute = localDateTime.getMinute();
17 int second = localDateTime.getSecond();
18 // DateTimeFormatter代替SimpleDateFormat
19 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
20 // Date格式化成String
21 String format = dateTimeFormatter.format(localDateTime);
22 LocalDateTime parse = LocalDateTime.parse(format, dateTimeFormatter);
23 ZoneOffset offset = OffsetDateTime.now().getOffset();
24 Instant instant2 = parse.toInstant(offset);
25 // 从String获得Date
26 Date from = Date.from(instant2);

说明:Java.time 这个包是线程安全的,所以可以替换之前的date类的使用。

Instant now = Instant.now();
System.out.println("now:"+now);

控制台输出:now:2018-07-09T08:59:08.853Z

通过这种方式获取的时间戳与北京时间相差8个时区,需要修正为北京时间,通过查看源代码发现Instant.now()使用等是UTC时间Clock.systemUTC().instant()。LocalDate、LocalDateTime 的now()方法使用的是系统默认时区 不存在Instant.now()的时间问题。

解决方法
如果要对应北京时间,需要增加8个小时

Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
System.out.println("now:"+now);

控制台输出:now:2018-07-09T16:58:48.188Z

LocalDateTime
它表示的是不带时区的 日期及时间,替换之前的Calendar。看上去,LocalDateTime和Instant很象,但记得的是“Instant中是不带时区的即时时间点。可能有人说,即时的时间点 不就是日期+时间么?看上去是这样的,但还是有所区别,比如LocalDateTime对于用户来说,可能就只是一个简单的日期和时间的概念,考虑如下的 例子:两个人都在2013年7月2日11点出生,第一个人是在英国出生,而第二个是在加尼福利亚,如果我们问他们是在什么时候出生的话,则他们看上去都是 在同样的时间出生(就是LocalDateTime所表达的),但如果我们根据时间线(如格林威治时间线)去仔细考察,则会发现在出生的人会比在英国出生的人稍微晚几个小时(这就是Instant所表达的概念,并且要将其转换为UTC格式的时间)。

实例代码如下:

 1 public static void main(String[] args) {
 2         //LocalDateTime 相当于calendar
 3         LocalDateTime localDateTime = LocalDateTime.now();
 4         System.out.println(localDateTime+" localDateTime1");
 5         //当前时间加上5小时,分钟等一样的用法,支持链式编程
 6         LocalDateTime localDateTime1 = localDateTime.plusHours(5);
 7         System.out.println(localDateTime1+" localDateTime1");
 8         //当前时间加上5小时,分钟等一样的用法,支持链式编程 但是这里localtime只是时间,不展示年月日,只展示如:15:26:50.398 时分秒毫秒
 9         LocalTime localDateTime2 = localDateTime.toLocalTime().plusHours(5);
10        //当前时间加上5天,只展示年月日,不展示时分秒毫秒,下面是两种写法,都可以
11         LocalDate localDate = localDateTime.toLocalDate().plusDays(5);
12         System.out.println(localDateTime2+" localDateTime2 "+localDate+ " localDate");
13         LocalDate plus = localDateTime.toLocalDate().plus(Period.ofDays(5));
14         System.out.println(plus+"  plus");
15  
16  
17     }

格式化日期

LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.now() ,ZoneId.systemDefault());
 
 String format = localDateTime.format(DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss"));
 System.out.println(format);

另一种方式使用会报错:

Instant now = Instant.now();
   
String format = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss").format(now);
 
system.out.println(format);

格式化日期并获取这一周内的数据

LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.now() ,ZoneId.systemDefault());
 
String createStartTp =localDateTime.plusDays(-6).format(DateTimeFormatter.ofPattern("yyyy/MM/dd 00:00:00"));
 
system.out.println(createStartTp);

 

posted @ 2019-07-12 11:29  smile_lg  阅读(2434)  评论(0编辑  收藏  举报