java8的时间和`Date`的对比 原 荐

栏目: 编程语言 · Java · 发布时间: 6年前

内容简介:java8提供了新的时间接口。相对date,time 在

java8的时间和 Date 的对比

java8提供了新的时间接口。相对 Date , Calendar ,个人感觉最大的好处是对时间操作的学习成本很低,比 Calendar 低。

1. LocalDate , LocalTime , LocalDateTime

LocalDate 代表日期, LocalTime 表示时刻,类似 11:23 这样的时刻。 LocalDateTime 就是前面2个的结合,这个可以从 java.time.LocalDateTime#toString 的代码看出一二:

@Override
public String toString() {
    return date.toString() + 'T' + time.toString();
}

date,time 在 java.time.LocalDateTime

/**
 * The date part.
 */
private final LocalDate date;
/**
 * The time part.
 */
private final LocalTime time;

实际使用中,计算日期就用 LocalDate ,计算日期加时刻用 LocalDateTime ,如果只有时刻就是 LocalTime (感觉在说废话) 这三个的用法基本上一样,通过方法名就知道用法那种

1.1 获取当前时间的对象

LocalDateTime.now localDateTime = LocalDateTime.now();
Date date = new Date();

localDateTime 相比 Date 更像是一个 工具 类,就是为了时间操作使用。其构造方法是私有的。

1.2 从字符串中解析

字符串 2019-01-11

String str = "2019-01-11";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate localDate = LocalDate.parse(str, formatter);

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
    Date date = simpleDateFormat.parse(str);
} catch (ParseException e) {
    e.printStackTrace();
}

DateTimeFormatter 的包路径是 java.time.formatLocalDate 一样在 java.time 下面,而 SimpleDateFormatDate 是不同的。所以当判断引入路径的时候更容易判断。 当解析失败的时候,两个异常的抛出不一样, DateTimeFormatter 抛出的是 DateTimeParseException ,继承自 RuntimeException ,而 ParseException 明显继承的是 Exception

个人感觉这个思路是,前者如果抛出异常那就是编程上错误,而后者则是的程序代码的不稳定性。我更倾向于第一种的异常设计,应该加强对入参的检测判断,而不是通过捕获异常去处理入参的错误。(类似NumberFormatException)

1.3 LocalDateDate 更强的初始化时间

Date 设置某个日期,基本上3个方式,时间戳/Calendar/字符串解析。相对的 LocalDate 就简单了很多

LocalDate.of(2019,1,12);

其他的也一样 java8的时间和`Date`的对比 原 荐

1.4 时间戳的转换

时间戳和时区关系的参考 时间转换代码参考

在这里时间戳的转换不如 Date 直接。主要因为LocalDate本身是没有时区的。

// 时间戳传LocalDateTime
long timestamp = System.currentTimeMillis();
Instant instant = Instant.ofEpochMilli(timestamp);
LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

#### LocalDateTime 转时间戳

LocalDateTime dateTime = LocalDateTime.now();
dateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
dateTime.toInstant(ZoneOffset.of("+08:00")).toEpochMilli();
dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

关于时区的计算也很简单,就是相差几个小时就加上多少秒 java8的时间和`Date`的对比 原 荐

有些时区计算的时候,不妨自己加时间也一样,elasticsearch+logstash设置@timestamp时间是默认UTC Z的时间,和咱们差了8个小时

LocalDateTime.parse(json.getString("@timestamp"), DateTimeFormatter.ISO_DATE_TIME).plusHours(8L)

1.5 和Date互转

import java.time.Instant;
import java.util.Date;

public class Main {
  public static void main(String[] args) {
    Date  dt =  new Date(); 
    System.out.println("Date: "  + dt);
    
    Instant in = dt.toInstant(); 
    System.out.println("Instant: "  + in);

    Date  dt2  = Date.from(in); 
    System.out.println("Date: "  + dt2);
  }
}

Instant 和 LocalDate或LocalDateTime 就不赘述了...

代码来自 Java 日期时间传统互操作性

1.6 更好的理解和操作方式

DateCalendar 的操作,例如设置月份,day of week 都有些让人迷惑,例如1月的定义是0,周一是0。1号好像也是0吧(我真没咋用过这东西,现用现百度...

LocalDate感觉好多了。例如 DayOfWeek 是枚举类型。使用枚举就不会理解错了吧 java8的时间和`Date`的对比 原 荐

很多日期和时间操作,无非就是加减时间和比较. 使用‘加’的示例: java8的时间和`Date`的对比 原 荐

不用再去使用一个不熟悉的 Calendar 去操作了(Calendar提供的接口都是啥玩意,get,set的)

Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1)

2. 线程安全性比较

LocalDate ...系列是线程安全的 额..每一个字段都用了 final 关键字了,都变不了... 所以进行操作后都是返回新的copy对象 java8的时间和`Date`的对比 原 荐

至于说 Date 线程不安全,get,set的肯定在多线程的时候容易出现问题,不过set方法已经都 @Deprecated 废弃了。当然不是因为线程安全问题废弃的,是因为有了更好的替代

Calendar.set(Calendar.DAY_OF_MONTH, int date)

不过感觉还是不如这个更清晰明了

LocalDate.of(2019,1,12);

2.1 SimpleDateFormat的线程安全性

参考: 深入理解Java:SimpleDateFormat安全的时间格式化

在一定负载情况下,SimpleDateFormat会出问题的。简单测试一下

package open.note;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;

public class UnSafeTest {

    private static String time = "2019-01-11 11:11:11";
    private static long timestamp = 1547176271000L;
    private static LocalDateTime dateTime = LocalDateTime.of(2019,1,11,11,11,11);
    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        dateFormatTest((obj)->{
            try {
                Date date = dateFormat.parse(time);
                if (date.getTime() != timestamp){
                    System.out.println(date);
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        });
        System.out.println("---------------");
        dateFormatTest((obj)->{
            try {
                LocalDateTime dateTime = LocalDateTime.parse(time,formatter);
                if (!dateTime.isEqual(UnSafeTest.dateTime)){
                    System.out.println(dateTime);
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        });
    }
    private static void dateFormatTest(Consumer runnable){
        CountDownLatch countDownLatch = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(()->{
                runnable.accept(null);
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果

multiple points
multiple points
empty String
Sat Jan 11 11:11:11 CST 111
Fri Jan 04 11:11:11 CST 2019
For input string: ""
Mon Dec 31 11:11:11 CST 2018
Mon Dec 31 11:11:11 CST 2018
For input string: ""
Tue Jan 11 11:11:11 CST 42101
---------------

测试过程中,SimpleDateFormat 1000个线程里,有5次,时间解析错了,5次异常了(时间错了,比抛出异常还可怕) DateTimeFormatter只是对比参考一下,未出现异常(人家已经声明是线程安全了...) 当然SimpleDateFormat线程不安全应该人尽皆知的,但依然有不安全的使用,但每次使用都new一个实例,当负载大的时候也不好。所以一个线程一个SimpleDateFormat实例应该可以的。

最后

java8 对时间操作的类还有很多 到 java.time 包下去看看,以后总会用得到的地方。

Instant:时间戳 Duration:持续时间,时间差 LocalDate:只包含日期,比如:2016-10-20 LocalTime:只包含时间,比如:23:12:10 LocalDateTime:包含日期和时间,比如:2016-10-20 23:14:21 Period:时间段 ZoneOffset:时区偏移量,比如:+8:00 ZonedDateTime:带时区的时间 Clock:时钟,比如获取目前美国纽约的时间

更多的示例参考


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Approximation Algorithms

Approximation Algorithms

Vijay V. Vazirani / Springer / 2001-07-02 / USD 54.95

'This book covers the dominant theoretical approaches to the approximate solution of hard combinatorial optimization and enumeration problems. It contains elegant combinatorial theory, useful and inte......一起来看看 《Approximation Algorithms》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具