简介
本文主要是对Java中常用的时间类做一下梳理,包括Java 8中新增的日期/时间类等,以及它们和时区的关联性
Date / Calendar
java.util.Date 是最常用的类之一,它的精度为毫秒,因为它的有些地方不合理,后来出现了Calendar来替代。java.util.Date 本身存储的是时间戳(1970年1月1日 00:00:00 GMT以来此对象表示的毫秒数 ),所以它和时区地域是无关的,只是在显示的时候加载了TimeZone来调整了时间的显示。
Calendar的getInstance()方法有参数为TimeZone和Locale的重载,可以使用指定时区和语言环境获得一个日历。无参则使用默认时区和语言环境获得日历。
public static Calendar getInstance(){
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}
// 重载的带有时区的方法
public static Calendar getInstance(TimeZone zone){
return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
}
我们来看下如下的代码
public class Te {
public static void main(String[] args) throws ParseException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 这边只是指定了这个SimpleDateFormat的时区为GMT时区,系统本身的时区还是默认的时区(中国时区)
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = new Date(1525518893403L);// 中国时间:2018-5-5 19:14:53
System.out.println(dateFormat.format(date));
// 字符串没有时区信息
String dateStr = "2018-05-05 19:14:53";
Date newDate = dateFormat.parse(dateStr);
System.out.println(newDate);
System.out.println(dateFormat.format(newDate));
}
}
output:
2018-05-05 11:14:53
Sun May 06 03:14:53 CST 2018 (对应的值为:2018-05-06 03:14:53)
2018-05-05 19:14:53
从上面的结果可以知道,Date是不带时区信息,所以在
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
后,输出的时间就是GMT时区的时间。
字符串的值被认为是GMT时间,所以newDate显示的时间是字符串时间 +8小时后的时间,从第三行输出也印证了这一点。
可以看到,上面的输出结果可能和我们预想的并不一致,Calendar 类作为新的类,没有那么复杂
public class Te {
public static void main(String[] args) throws ParseException {
Date date = new Date(1525518893403L);// 中国时间:2018-5-5 19:14:53
System.out.println(date);
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.setTime(date);
System.out.println(calendar.getTime());
System.out.println(calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH) + "-" +
calendar.get(Calendar.DAY_OF_MONTH) + " " +
calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE) + ":" +
calendar.get(Calendar.SECOND));
}
}
output:
Sat May 05 19:14:53 CST 2018
Sat May 05 19:14:53 CST 2018
2018-4-5 11:14:53
可以看到,我们在使用Calendar的时候,获取时间不能直接使用getTime(),因为其返回的是一个Date,而Date是没有时区信息的,应该使用calendar.get()方法。
java.sql.Date / java.sql.Timestamp
这两个类都和数据库有关系,看报名就知道了。且他们都是java.util.Date 的子类。因此,类似的,他们也都没有时区信息。
java.sql.Date 是只保留年月日,而没有时分秒信息,对应数据库(eg. mysql)中的date类型.
java.sql.Timestamp 精确到纳秒,对应数据库(eg.mysql)中的timestamp类型
java8 新增的日期时间类
- Instant:瞬时实例。
-
LocalDate:本地日期,不包含具体时间。例如:
2014-01-14
可以用来记录生日、纪念日、加盟日等。 - LocalTime:本地时间,不包含日期。
- LocalDateTime:组合了日期和时间,但不包含时差和时区信息。
- ZonedDateTime:最完整的日期时间,包含时区和相对UTC或格林威治的时差。
Instant
Instant 以Unix时间戳的形式存储日期时间 ,
精确到纳秒
// 获取当前的时间戳
Instant timestamp = Instant.now();
System.out.println(timestamp);
// 类似的,从指定的时间戳生成 Instant
Instant specificTime = Instant.ofEpochMilli(System.currentTimeMillis());
System.out.println(specificTime);
output:
2018-05-05T12:44:54.037Z
2018-05-05T12:44:54.195Z
Instant 和Date类似,没有时区信息(也可以认为是0时区,即GMT时区)
ZonedDateTime
java8 把时区也分离出来了,现在转换时区很方便。如果要显示指定的时区,可以使用 ZonedDateTime
ZonedDateTime result=ZonedDateTime.ofInstant(Instant.now(),ZoneId.systemDefault());
System.out.println(result);
// ZonedDateTime 底层就是用Instant存储的
System.out.println(result.toInstant());
output:
2018-05-05T20:52:04.096+08:00[Asia/Shanghai]
2018-05-05T12:52:04.096Z
下面这个例子是时区的转换
//获取当前时区的日期时间
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
System.out.println(now.withZoneSameInstant(ZoneId.of("America/New_York")));
//获取美国洛杉矶时区的日期时间,写这段代码的时候,北京时间是 2018-05-05 21:53:26,下面等于是生成了了纽约时间 2018-05-05 21:53:26。因为ZonedDateTime底层是用Instant存储的,所以USANow内的Instant的值和上面now的Instant值是不相等的。
ZonedDateTime USANow = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("America/New_York"));
System.out.println(USANow);
System.out.println(USANow.withZoneSameInstant(ZoneId.systemDefault()));
output:
2018-05-05T21:53:26.322+08:00[Asia/Shanghai]
2018-05-05T09:53:26.322-04:00[America/New_York]
2018-05-05T21:53:26.356-04:00[America/New_York]
2018-05-06T09:53:26.356+08:00[Asia/Shanghai]
相比与之前的时区转换,ZonedDateTime的操作是简便了很多,更便于理解
LocalDate / LocalTime
如上面介绍的所示,一个只有日期,一个只有时间,
两者都是没有指定时区的
“`java
LocalDate today = LocalDate.now();
System.out.println(today);
LocalTime now = LocalTime.now();
System.out.println(now);
output:
2018-05-05
21:00:27.979
LocalDate还提供了很多有用的方法
```java
// 构造日期
LocalDate date = LocalDate.of(2016, 4, 18);
LocalDate date2 = LocalDate.of(2016, 5, 18);
//比较两者相等
if (!date.equals(date2)) {
System.out.printf("date %s 和 date2 %s 不是同一天!%n", date, date2);
}
LocalDateTime是两者的聚合体,这里就不写了,这些类都有一些很好用的方法,查API文档即可,这里就不浪费时间记述了,浪费大家的时间
转载于:https://www.cnblogs.com/hinsy/p/9672835.html