一篇文章掌握java时间所有场景——GMT、UTC、CST,各种日期格式转换Date、String、LocalDate、LocalDateTime
一、基本概念
时区由来
为了克服时间上的混乱,1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为中时区(零时区)、东1—12区,西1—12区。每个时区横跨经度15度,时间正好是1小时。最后的东、西第12区各跨经度7.5度,以东、西经180度为界。每个时区的中央经线上的时间就是这个时区内统一采用的时间,称为区时,相邻两个时区的时间相差1小时。
百度百科:时区
GMT、UTC、CST、ISO的概念
- GMT:格林尼治时间(旧的世界标准时间)
- UTC:世界协调时间(新的世界标准时间)
- CST:中国标准时间,China Standard Time UT+8:00
- ISO:在时间日期上它全称是ISO 8601,是一种日期/时间表示方法的规范;规定了一种明确的、国际上都能理解的日历和时钟格式。如Java中的: - ISO.DATE:yyyy-MM-dd, e.g. “2000-10-31”
科普:24时区,GMT,UTC,DST,CST时间详解
闰秒概念
闰秒,是指为保持协调世界时接近于世界时时刻,由国际计量局统一规定在年底或年中(也可能在季末)对协调世界时增加或减少1秒的调整。由于地球自转的不均匀性和长期变慢性(主要由潮汐摩擦引起的),会使世界时(民用时)和原子时之间相差超过到±0.9秒时,就把协调世界时向前拨1秒(负闰秒,最后一分钟为59秒)或向后拨1秒(正闰秒,最后一分钟为61秒); 闰秒一般加在公历年末或公历六月末。
百度百科:闰秒
二、基础类库及常用方法
java.lang.System类
- public static native long currentTimeMillis();
以毫秒为单位返回当前时间。请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统,可能更大。例如,许多操作系统以几十毫秒为单位测量时间。
有关“计算机时间”和协调世界时(UTC)之间可能出现的细微差异的讨论,请参阅类日期的描述。
返回:当前时间与1970年1月1日UTC午夜之间的差值,以毫秒为单位。
java.util.Date类
- public Date();
- public Date(long date);
分配一个Date对象并将其初始化,以表示自标准基准时间“epoch”(即1970年1月1日00:00:00 GMT)以来的指定毫秒数。
参数:date -从1970年1月1日00:00:00 GMT开始的毫秒数。 - public long getTime();
- public static Date from(Instant instant);
- public Instant toInstant();
java.time.LocalDate;
- public static LocalDate now();
- public static LocalDate of(int year, int month, int dayOfMonth);
- public static LocalDate parse(CharSequence text, DateTimeFormatter formatter);
- public LocalDate plusDays(long daysToAdd);
- public String format(DateTimeFormatter formatter);
- public long toEpochDay();
- public LocalDateTime atTime(LocalTime time);
- public LocalDateTime atTime(int hour, int minute, int second);
java.time.LocalTime;
- public static LocalTime now()
- public static LocalTime of(int hour, int minute, int second)
- public static LocalTime parse(CharSequence text, DateTimeFormatter formatter)
- public String format(DateTimeFormatter formatter)
- public LocalDateTime atDate(LocalDate date)
java.time.LocalDateTime;
- public static LocalDateTime now()
- public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second)
- public static LocalDateTime of(LocalDate date, LocalTime time)
- public static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter)
- public LocalDate toLocalDate()
- public LocalTime toLocalTime()
- public String format(DateTimeFormatter formatter)
java.util.Calendar
- public static Calendar getInstance()
获取使用默认时区和区域设置的日历。返回的Calendar基于默认时区的当前时间,具有默认的FORMAT区域设置。
返回:日历 - public long getTimeInMillis()
- public final Date getTime()
- public final void set(int year, int month, int date, int hourOfDay, int minute, int second)
小结
public static void test() {
System.out.println(System.currentTimeMillis());
Date date = new Date();
System.out.println(date.getTime());
Calendar calendar = Calendar.getInstance();
Date date2 = calendar.getTime();
System.out.println(date2.getTime());
System.out.println(calendar.getTimeInMillis());
System.out.println(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
}
以上可以看到LocalDateTime.now()生成的时间是不带时区或者偏移量的,转换的时候就需要计算上。
三、实战应用
import cn.hutool.core.date.DatePattern;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
public class DateTimeUtil {
public static Date toDate(String dateStr, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date;
try {
date = sdf.parse(dateStr);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return date;
}
public static String toDateStr(Date date, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
String str = sdf.format(date);
return str;
}
public static Date toDate(LocalDateTime localDateTime, ZoneOffset offset) {
Date date = new Date(localDateTime.toInstant(offset).toEpochMilli());
return date;
}
public static LocalDateTime toLocalDateTime(Date date, ZoneId zoneId) {
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), zoneId);
return localDateTime;
}
public static void main(String[] args) {
Date date = DateTimeUtil.toDate("2023-11-25 15:15:21", DatePattern.NORM_DATETIME_PATTERN);
System.out.println(date);
String dateStr = DateTimeUtil.toDateStr(date, DatePattern.NORM_DATETIME_PATTERN);
System.out.println(dateStr);
// LocalDateTime localDateTime = DateTimeUtil.toLocalDateTime(date, ZoneId.of("CTT", ZoneId.SHORT_IDS));
LocalDateTime localDateTime = DateTimeUtil.toLocalDateTime(date, ZoneId.systemDefault());
System.out.println(localDateTime);
Date date1 = DateTimeUtil.toDate(localDateTime, ZoneOffset.of("+8"));
System.out.println(date1);
Date date2 = DateTimeUtil.toDate(LocalDateTime.of(2023, 11, 25, 15, 15, 21), ZoneOffset.of("+8"));
System.out.println(date.getTime() == date2.getTime());
Calendar calendar = Calendar.getInstance();
calendar.set(2023, 11, 25, 15, 15, 21);
System.out.println(calendar.getTime());
System.out.println(date.getTime());
System.out.println(calendar.getTimeInMillis());
System.out.println(date.getTime() == calendar.getTimeInMillis()); // 精度不够,约等于
}
}