11.4 Java 日期和时间类

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 我们先来看一些基本概念,然后再介绍 Java 的日期和时间 API。关于日期和时间,有一些基本概念,包括时区、时刻、纪元时、年历等。全球一共有 24 个时区,英国格林尼治是 0 时区,北京是东八区,也就是说格林尼治凌晨 1 点,北京是早上 9 点。0 时区的时间也称为 GMT+0 时间,GMT 是格林尼治标准时间,北京的时间就是 GMT+8:00。所有计算机系统内部都用一个整数表示时刻,这个整数是距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。为什么要用这个时间呢?更多的是历史原因。格林尼治标准时间 1970年1月1日0时0分0秒也被称为 Epoch Time(纪元时)

我们先来看一些基本概念,然后再介绍 Java 的日期和时间 API。关于日期和时间,有一些基本概念,包括时区、时刻、纪元时、年历等。


全球一共有 24 个时区,英国格林尼治是 0 时区,北京是东八区,也就是说格林尼治凌晨 1 点,北京是早上 9 点。0 时区的时间也称为 GMT+0 时间,GMT 是格林尼治标准时间,北京的时间就是 GMT+8:00。


所有计算机系统内部都用一个整数表示时刻,这个整数是距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。为什么要用这个时间呢?更多的是历史原因。


格林尼治标准时间 1970年1月1日0时0分0秒也被称为 Epoch Time(纪元时)。


我们都知道,中国有公历和农历之分,公历和农历都是年历,不同的年历,一年有多少月,每月有多少天,甚至一天有多少小时,这些可能都是不一样的。


公历是世界上广泛采用的年历,除了公历,还有其他一些年历,比如日本也有自己的年历。Java API 的设计思想是支持国际化的,支持多种年历,但没有直接支持中国的农历,本书主要讨论公历。


时间标准介绍



格林尼治标准时间(GMT,旧译“格林威治平均时间”或“格林威治标准时间”)是指位于伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。


世界协调时(UTC)  英文:Coordinated Universal Time ,别称:世界统一时间,世界标准时间国际协调时间, 协调世界时,又称世界统一时间,世界标准时间,国际协调时间,简称 UTC。它从英文“Coordinated Universal Time”/法文“Temps Universel Cordonné”而来。


1979 年 12 月初内瓦举行的世界无线电行政大会通过决议,确定用“世界协调时间”取代“格林威治时间”,作为无线电通信领域内的国际标准时间。


格林威治时间是多年来人们所熟知的国际标准时间,为什么要改用世界协调时间呢?简单说来,是因为格林威治时间不够精确。格林威治时间是以地球自转为基础的一种时标,由于地球自旋轴每年有一定波动,致使时间每年产生将近一秒钟的误差。因此,为了适应现代科学技术的发展,迫切需要有一种更精确的国际标准时间。


世界协调时间是根据地球相对于转轴的波动、旋转速率以及极移效应对太阳时进行不断校正的一种协调时间。国际时间局每年进行两次调整,并通过标准时间电台向世界各地发射标准时间信号,这样就可以把格林威治时间产生的一秒钟误差调整过来。


这套时间系统被应用于许多互联网和万维网的标准中,例如,网络时间协议就是协调世界时在互联网中使用的一种方式。


CST 时间可以为如下 4 个不同的时区的缩写


  1. 美国中部时间:Central Standard Time (USA) UT-6:00


  1. 古巴标准时间:Cuba Standard Time UT-4:00


  1. 中国标准时间:China Standard Time UT+8:00


  1. 澳大利亚中部时间:Central Standard Time (Australia) UT+9:30


可见,CST 可以同时表示美国,澳大利亚,中国,古巴四个国家的标准时间。


在军事中,协调世界时区会使用“Z”来表示。又由于Z在无线电联络中使用“Zulu”作代称,协调世界时也会被称为"Zulu time"。


Java 8 之前的日期和时间 API



Java 8 之前日期类是 java.util.Date,Date 类比较古老,其中的很多方法现在已经废弃了,但是目前仍然有很多程序还在使用 Date 类。此外 DateFormat 用于日期格式化,Calendar 日历类,TimeZone 是时区类。 Locale 表示国家(或地区)和语言。


Date 类


new Date() 用当前日期和时间创建新的日期对象:


new Date(milliseconds) 创建一个零时加毫秒的新日期对象


返回从 1970 年 1月 1 日0时0分0 秒(UTC,即世界协调时)距离该日期对象所代表时间的毫秒数。


// 从 1970 年1月1日 早上 8 点 0 分 0 秒 开始经历的时间
System.out.println(d3);
// 当前日期的毫秒数
System.out.println(d3.getTime());


输出

Thu Jan 01 08:00:00 AWST 1970
0


Calendar 类


有时为了取得更多的日期时间信息,或对日期时间进行操作,可以使用

java.util.Calendar 类,Calendar 是一个抽象类,不能实例化,但是通过静态工厂方法 getInstance() 获得 Calendar 实例。


Calendar类的主要方法:


  • static Calendar getInstance():使用默认时区和语言环境获得一个日历。


  • void set(int field, int value):将给定的日历字段设置为给定值。


  • void set(int year,int month,int date):设置日历字段 YEAR、MONTH和DAY_OF_MONTH 的值。


  • Date getTime():返回一个表示此 Calendar 时间值(从 1970年1月1日00:00:00 至现在的毫秒数)的Date对象。


  • boolean after(Object when):判断此 Calendar 表示的时间是否在指定时间之后,返回判断结果。


  • boolean before(Object when):判断此 Calendar 表示的时间是否在指定时间之前,返回判断结果。


  • int compareTo(Calendar anotherCalendar):比较两个Calendar对象表示的时间值。


TimeZone


TimeZone 表示时区,它是一个抽象类,有静态方法用于获取其实例。获取当前的默认时区。


Java中有一个系统属性 user.timezone,保存的就是默认时区。系统属性可以通过System.getProperty 获得。


系统属性可以在 Java 启动的时候传入参数进行更改。


TimeZone也有静态方法,可以获得任意给定时区的实例。


TimeZone tz = TimeZone.getTimeZone("GMT+08:00");


Locale


Locale 表示国家(或地区)和语言,它有两个主要参数:一个是国家(或地区);另一个是语言,每个参数都有一个代码,不过国家(或地区)并不是必需的。比如,中国内地的代码是 CN,中国台湾地区的代码是 TW,美国的代码是 US,中文语言的代码是 zh,英文语言的代码是 en。Locale 类中定义了一些静态变量,表示常见的 Locale。


System.out.println(Locale.getDefault());


本机中输出为 zh_CN。


DateFormat 日期时间格式化


日期格式化用到的是 java.text.DateFormat,DateFormat 是抽象类,它的常用子类是 java.text.SimpleDateFormat。


DateFormat 中提供日期格式化和日期解析方法,具体方法说明如下:


  • String format(Date date):将一个 Date 格式化为日期/时间字符串。


  • Date parse(String source):从给定字符串的开始解析文本,以生成一个日期对象。如果解析失败则抛出 ParseException。


与Calendar类似,DateFormat 也是抽象类,也用工厂方法创建对象,提供了多个静态方法创建DateFormat 对象。


DateFormat 的工厂方法里,我们没看到 TimeZone 参数,不过,DateFormat 提供了一个 setter 方法,可以设置TimeZone。


另外,具体类是 SimpleDateFormat 构造方法如下:


  • SimpleDateFormat():用默认的模式和默认语言环境的日期格式符号构造SimpleDateFormat。


  • SimpleDateFormat(String pattern):用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。pattern参数是日期和时间格式模式,下表所示是常用的日期和时间格式模式。


网络异常,图片无法展示
|


Joda-Time 是 Java SE 8 之前的行业标准日期和时间库



Joda-Time 为 Java 日期和时间类提供了质量替代。现在要求用户迁移到 java.time (JSR-310)。


官网 https://www.joda.org/joda-time/index.html


A selection of key features:


  • LocalDate - date without time


  • LocalTime - time without date


  • Instant - an instantaneous point on the time-line


  • DateTime - full date and time with time-zone


  • DateTimeZone - a better time-zone


  • Duration and Period - amounts of time


  • Interval - the time between two instants


2.10.13 是当前的最新版本。这个版本被认为是稳定的,是值得使用 2.x 版本。


Joda-Time 需要 java SE 5 或更高版本,并且没有任何依赖项。Joda-Convert 上有一个编译时依赖项,但由于有神奇的注释,这在运行时不是必需的。


<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.10.13</version>
</dependency>


Java 8 的日期和时间 API



Java 8 之前的API存在着一些局限性,例如 Date 中的方法参数与常识不符合,过时方法标记容易被人忽略,产生误用。Calendar 操作比较烦琐。


DateFormat/SimpleDateFormat 不是线程安全的。Java 8 之后提供了新的日期时间相关类、接口和枚举,这些类型内容非常多。但是使用起来非常方便。


Java 8 之后提供了新的日期时间类有三个:LocalDate、LocalTime 和LocalDateTime,它们都位于 java.time 包中,LocalDate 表示一个不可变的日期对象;LocalTime 表示一个不可变的时间对象;LocalDateTime 表示一个不可变的日期和时间。


Instant 时刻


时间戳是自 1970 年 1 月 1 日(00:00:00)以来的秒数。它也被称为 Unix 时间戳(Unix Timestamp)。

Instant.now() 使用等是 UTC 时间 Clock.systemUTC().instant(),所以不存在偏移量。


System.out.println("获得10位秒数:" + now.getEpochSecond());


System.out.println("获得13位毫秒数:" + now.toEpochMilli());


Java 8 的时间戳(毫秒值):Instant.now().toEpochMilli()


LocalDate/LocalTime/LocalDateTime


LocalDateTime——不含时间信息的日期


LocalTime——不含日期信息的时间


LocalDateTime——包含了日期及时间信息


不包含没有偏移信息或者说时区。


这三个类有类似的方法,首先先看看创建日期时间对象相关方法,这三个类并没有提供公有的构造方法,创建它们对象可以使用静态工厂方法,主要有 now() 和 of() 方法。


LocalDate 不包含具体时间的日期,比如 2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。


LocalDate.now();
LocalDate.of(2011, 1, 3);


now()方法说明如下:


  • static LocalDate now():LocalDate 静态工厂方法,该方法使用默认时区获得当前日期,返回LocalDate对象。


  • static LocalTime now():LocalTime 静态工厂方法,该方法使用默认时区获得当前时间,返回LocalTime对象。


  • static LocalDateTime now():LocalDateTime 静态工厂方法,该方法使用默认时区获得当前日期时间,返回 LocalDateTime 对象。


of() 方法有很多重载方法,说明如下:


  • static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second):按照指定的年、月、日、小时、分钟和秒获得 LocalDateTime 实例,将纳秒设置为零。


  • static LocalTime of(int hour, int minute, int second):按照指定的小时、分钟和秒获取一个LocalTime实例。


  • static LocalDate of(int year, int month, int dayOfMonth):按照指定的年、月和日获得一个LocalDate实例,日期中年、月和日必须有效,否则将抛出异常。

在 java 8 中检查两个日期可以继续使用 equals 。


网络异常,图片无法展示
|


参数取值范围


Java 8 的日期格式化和解析


Java 8 提供的日期格式化类是 java.time.format.DateTimeFormatter,

DateTimeFormatter 中本身没有提供日期格式化和日期解析方法,这些方法还是由 LocalDate、LocalTime 和 LocalDateTime 提供的。


  1. 日期格式化
    日期格式化方法是 format,这三个类每一个都有 String format(DateTimeFormatter formatter),参数 formatter 是 DateTimeFormatter 类型。


  1. 日期解析
    日期解析方法是 parse,这三个类每一个都有两个版本的 parse 方法,具体说明如下:


  • static LocalDateTime parse(CharSequence text):使用默认格式,从一个文本字符串获取一个LocalDateTime实例,如2007-12-03T10:15:30。


  • static LocalDateTime parse(CharSequence text, DateTimeFormatter formatter):使用指定格式化,从文本字符串获取LocalDateTime实例。


  • static LocalDate parse(CharSequence text):使用默认格式,从一个文本字符串获取一个LocalDate实例,如2007-12-03。


  • static LocalDate parse(CharSequence text, DateTimeFormatter formatter):使用指定格式化,从文本字符串获取LocalDate实例。


  • static LocalTime parse(CharSequence text):使用默认格式,从一个文本字符串获取一个LocalTime实例。


  • static LocalTime parse(CharSequence text, DateTimeFormatter formatter):使用指定的格式化,从文本字符串获取LocalTime实例。


格式化类 DateTimeFormatter 对象是通过ofPattern(String pattern)获得,其中pattern 是日期和时间格式模式,具体说明参考上上表。


String 转 LocalDate,String 转换成该对象,用到了parse关键字


LocalDate.parse("20210212", DateTimeFormatter.BASIC_ISO_DATE);


指定时区获取当前时间


LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai")))


自定义的格式器来解析日期

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM dd yyyy");
d.parse(goodFriday, formatter)


转换成 String 用到了 format

LocatDate time;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM dd yyyy HH:mm:ss");
String result = time.format(formatter);


ZonId 代表的是某个特定时区


ZonedDateTime 代表带时区的时间



ZonedDateTime 表示特定时区的日期和时间,获取系统默认时区的当前日期和时间。


LocalDateTime.now() 也是获取默认时区的当前日期和时间,有什么区别呢?Local-DateTime 内部不会记录时区信息,只会单纯记录年月日时分秒等信息,而

ZonedDateTime 除了记录日历信息,还会记录时区,它的其他大部分构建方法都需要显式传递时区。


互转操作


Instant 转换成 java.util.date


Date.from(Instant)


java.util.date 转换成Instant


Date.toInstant()


时间 API 遗留代码的互相操作


// Date --> Instant


Instant timestamp = new Date().toInstant();


// Instant --> Date


Date.from(Instant.now());


// GregorianCalendar --> ZonedDateTime


new GregorianCalendar().toZonedDateTime();


//  ZonedDateTime --> GregorianCalendar


GregorianCalendar.from(zonedDateTime);


最新 JDBC 映射将把数据库的日期类型和 Java 8 的新类型关联起来:


SQL -> Java
--------------------------
date -> LocalDate
time -> LocalTime
timestamp -> LocalDateTime


LocalDateTime.now() 慢了8个小时的问题排查


原因是 java 代码中将 new Date() 插入到 mysql 的对应 timestamp 类型的字段中


修改 jdbc 链接为:&serverTimezone=Asia/Shanghai


或 serverTimezone=GMT%2B8


Java 时间 API 完整案例

package qy.basic.ch11;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class DateMain {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date);
        // Locale 表示国家和语言
        Locale locale = Locale.getDefault();
        System.out.println(locale);
        // TimeZone 表示时区
        TimeZone timeZone = TimeZone.getDefault();
        System.out.println(timeZone);
        // 常用时区
        System.out.println(TimeZone.getTimeZone("UTC"));
        System.out.println(TimeZone.getTimeZone("GMT+8"));
        System.out.println(TimeZone.getTimeZone("GMT+8:00"));
        System.out.println(TimeZone.getTimeZone("Zulu"));
        // 遍历所有可用时区的 ID
        System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));
        // Calendar 表示日历,在中国一般是格林尼治公历
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar);
        System.out.println(calendar.get(Calendar.YEAR) + "-" + (1 + calendar.get(Calendar.MONTH)) + "-"+ calendar.get(Calendar.DAY_OF_MONTH));
        // Calendar 转 Date
        Date time = calendar.getTime();
        System.out.println(time);
        // DateFormat 使用
        System.out.println(DateFormat.getDateInstance().format(date));
        System.out.println(DateFormat.getTimeInstance().format(date));
        System.out.println(DateFormat.getDateTimeInstance().format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date));
        // 指定 Locale 信息
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.TRADITIONAL_CHINESE).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.FRANCE).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.GERMAN).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.UK).format(date));
        System.out.println(DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US).format(date));
        // 使用 SimpleDateFormat
        System.out.println(new SimpleDateFormat("yyy-MM-dd HH:mm:ss SSS").format(date));
        // 不会存在偏移量
        System.out.println("--------Instant--------");
        Instant instant = Instant.now();
        System.out.println(instant);
        System.out.println(instant.toEpochMilli());
        // ZoneOffset 是 Java 8 新增的方法,是 ZoneId 的子类
        System.out.println("--------ZoneOffset--------");
        System.out.println(ZoneOffset.getAvailableZoneIds());
        System.out.println(ZoneOffset.of("+8"));
        System.out.println(ZoneOffset.UTC);
        // LocalDateTime 转 Instant
        LocalDateTime localDateTime = LocalDateTime.now();
        // 将抛掉8小时 -8
        System.out.println(localDateTime.toInstant(ZoneOffset.of("+8")));
        System.out.println(localDateTime.toInstant(ZoneOffset.UTC));
        System.out.println("------LocalDateTime 通过 of 进行构建-----");
        System.out.println(LocalDateTime.of(2022, 1, 2, 3, 4,5, 666));
        // 北京当地时间 通过传入 ZoneId
        System.out.println(LocalDateTime.now(ZoneId.of("GMT+8")));
        // 北京当地时间 通过传入 ZoneOffset 进行构建
        System.out.println(LocalDateTime.now(ZoneOffset.of("+8")));
        // 给定一个时刻,使用不同时区解读,日历信息是不同的
        // 这里指定北京时区
        ZonedDateTime atZone = Instant.now().atZone(ZoneId.of("GMT+8"));
        System.out.println(atZone);
        System.out.println(Instant.now().atZone(ZoneId.of("Z")));
        // ZonedDateTime表示特定时区的日期和时间,获取系统默认时区的当前日期和时间
        // 构建:通过 now 进行构建
        System.out.println(ZonedDateTime.now());
        // 构建:使用 Instant 构建 ZonedDateTime
        System.out.println(ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()));
        // 构建:使用 LocalDateTime 构建 ZonedDateTime, 会结合系统本地的时区
        System.out.println(LocalDateTime.now().atZone(ZoneId.systemDefault()));
        // 转换:ZonedDateTime 转 Instant
        System.out.println(ZonedDateTime.now().toInstant());
        // 转换:ZonedDateTime 转 LocalDateTime 
        System.out.println(ZonedDateTime.now().toLocalDateTime());
        // UTC 时钟
        final ZoneId utcZoneId = Clock.systemUTC().getZone();
        // 系统时钟
        final ZoneId defaultZoneId = ZoneId.systemDefault();
        // 上海时钟
        final ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
        // 东京时钟
        final ZoneId tokyoZoneId = ZoneId.of("Asia/Tokyo");
        System.out.println("--------ZoneId--------");
        System.out.println(utcZoneId);
        System.out.println(defaultZoneId);
        System.out.println(shanghaiZoneId);
        System.out.println(tokyoZoneId);
        // 通过 ZoneId 得到 Clock
        System.out.println("--------借助 ZoneId 生成 Clock--------");
        final Clock utcClock = Clock.systemUTC();
        final Clock defaultClock = Clock.systemDefaultZone();
        final Clock shanghaiClock = Clock.system(shanghaiZoneId);
        final Clock tokyoClock = Clock.system(tokyoZoneId);
        System.out.println(utcClock);
        System.out.println(defaultClock);
        System.out.println(shanghaiClock);
        System.out.println(tokyoClock);
        // 通过 Clock 拿到 ZoneId
        System.out.println("--------通过 Clock 拿到 ZoneId--------");
        System.out.println(utcClock.getZone());
        System.out.println(defaultClock.getZone());
        System.out.println(shanghaiClock.getZone());
        System.out.println(tokyoClock.getZone());
        System.out.println("------通过 now 方法Instant------");
        System.out.println(Instant.now());
        System.out.println(Instant.now(utcClock));
        System.out.println(Instant.now(defaultClock));
        System.out.println(Instant.now(shanghaiClock));
        System.out.println(Instant.now(tokyoClock));
        System.out.println("-------通过 Clock 的快捷方法构建 Instant --");
        System.out.println(utcClock.instant());
        System.out.println(defaultClock.instant());
        System.out.println(shanghaiClock.instant());
        System.out.println(tokyoClock.instant());
        System.out.println("------反解析 parse 和 of 及其类似----------");
        // 字符串 反解析为 localDateTime
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
        System.out.println(dateTimeFormatter.getLocale());
        System.out.println(dateTimeFormatter.getZone());
        LocalDateTime ldt = LocalDateTime.parse("2018-06-01 10:12:05", dateTimeFormatter);
        System.out.println("LocalDateTime: " + ldt);
        System.out.println("LocalDateTime ISO_DATE_TIME formatter: " + ldt.format(DateTimeFormatter.ISO_DATE_TIME));
        System.out.println("LocalDateTime ISO_LOCAL_DATE_TIME formatter: " + ldt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        System.out.println("LocalDateTime BASIC_ISO_DATE formatter: " + ldt.format(DateTimeFormatter.BASIC_ISO_DATE));
        System.out.println("LocalDateTime ISO_LOCAL_DATE formatter: " + ldt.format(DateTimeFormatter.ISO_LOCAL_DATE));
        System.out.println("--------test instant2ZonedDateTime--------");
        System.out.println(instant2ZonedDateTime(Instant.now()));
    }
    /**
     * Date 2 LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(final Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }
    /**
     * LocalDateTime 2 Date   (该类也是不带时区信息的哦)
     */
    public static Date localDateTime2Date(final LocalDateTime time) {
        // 通过 ZonedDateTime 进行中转
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }
    /**
     * LocalDateTime 2 ZonedDateTime
     */
    public static ZonedDateTime localDateTime2ZonedDateTime(final LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault());
    }
    /**
     * Instant 2 ZonedDateTime
     */
    public static ZonedDateTime instant2ZonedDateTime(final Instant instant) {
        return instant.atZone(ZoneId.systemDefault());
    }
}


四种预定义 DateTimeFormatter。


LocalDateTime ISO_DATE_TIME formatter: 2018-06-01T10:12:05


LocalDateTime ISO_LOCAL_DATE_TIME formatter: 2018-06-01T10:12:05


LocalDateTime BASIC_ISO_DATE formatter: 20180601


LocalDateTime ISO_LOCAL_DATE formatter: 2018-06-01


我的总结



获取时间戳,使用最原始的 Instant.now(); 即可,因为不包含时区差异,所以不会存在偏移量。


Java 8 新增了 ZoneOffset 和 ZoneId。其中 ZoneOffset 是 ZoneId 的子类。如果要输出指定时区的时间情况下可以使用。


ZoneOffset.of("+8") 可表示东八区。建议使用。ZoneOffset.UTC 表示世界协调时。这两个用得较多。


参考



  • Java 编程的逻辑-微信读书

https://weread.qq.com/web/reader/b51320f05e159eb51b29226kc81322c012c81e728d9d180




目录
相关文章
|
7天前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
21 1
|
7天前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
18 0
java基础(13)String类
|
18天前
|
Java 编译器
Java——类与对象(继承和多态)
本文介绍了面向对象编程中的继承概念,包括如何避免重复代码、构造方法的调用规则、成员变量的访问以及权限修饰符的使用。文中详细解释了继承与组合的区别,并探讨了多态的概念,包括向上转型、向下转型和方法的重写。此外,还讨论了静态绑定和动态绑定的区别,以及多态带来的优势和弊端。
22 9
Java——类与对象(继承和多态)
|
18天前
|
SQL Java 编译器
Java——类与对象(封装)
封装是面向对象编程中的概念,指将数据(属性)和相关操作(方法)组合成独立单元(类),使外部无法直接访问对象的内部状态,只能通过提供的方法进行交互,从而保护数据安全。例如,手机将各种组件封装起来,只暴露必要的接口供外部使用。实现封装时,使用`private`关键字修饰成员变量,并提供`get`和`set`方法进行访问和修改。此外,介绍了包的概念、导入包的方式及其注意事项,以及`static`关键字的使用,包括静态变量和方法的初始化与代码块的加载顺序。
22 10
Java——类与对象(封装)
|
18天前
|
Java C语言
Java——类与对象
这段内容介绍了Java中的类和对象、`this`关键字及构造方法的基本概念。类是对现实世界事物的抽象描述,包含属性和方法;对象是类的实例,通过`new`关键字创建。`this`关键字用于区分成员变量和局部变量,构造方法用于初始化对象。此外,还介绍了标准JavaBean的要求和生成方法。
21 9
Java——类与对象
|
17天前
|
存储 安全 Java
Java——String类详解
String 是 Java 中的一个类,用于表示字符串,属于引用数据类型。字符串可以通过多种方式定义,如直接赋值、创建对象、传入 char 或 byte 类型数组。直接赋值会将字符串存储在串池中,复用相同的字符串以节省内存。String 类提供了丰富的方法,如比较(equals() 和 compareTo())、查找(charAt() 和 indexOf())、转换(valueOf() 和 format())、拆分(split())和截取(substring())。此外,还介绍了 StringBuilder 和 StringJoiner 类,前者用于高效拼接字符串,后者用于按指定格式拼接字符串
16 1
Java——String类详解
|
2天前
|
Java 数据库
java小工具util系列1:日期和字符串转换工具
java小工具util系列1:日期和字符串转换工具
10 3
|
8天前
|
存储 Java
Java编程中的对象和类
【8月更文挑战第55天】在Java的世界中,“对象”与“类”是构建一切的基础。就像乐高积木一样,类定义了形状和结构,而对象则是根据这些设计拼装出来的具体作品。本篇文章将通过一个简单的例子,展示如何从零开始创建一个类,并利用它来制作我们的第一个Java对象。准备好让你的编程之旅起飞了吗?让我们一起来探索这个神奇的过程!
25 10
|
1天前
|
Java API
Java的日期类都是怎么用的
【10月更文挑战第1天】本文介绍了 Java 中处理日期和时间的三个主要类:`java.util.Date`、`java.util.Calendar` 和 `java.time` 包下的新 API。`Date` 类用于表示精确到毫秒的瞬间,可通过时间戳创建或获取当前日期;`Calendar` 抽象类提供丰富的日期操作方法,如获取年月日及时区转换;`java.time` 包中的 `LocalDate`、`LocalTime`、`LocalDateTime` 和 `ZonedDateTime` 等类则提供了更为现代和灵活的日期时间处理方式,支持时区和复杂的时间计算。
24 13
|
4天前
|
安全 Java API
时间日期API(Date,SimpleDateFormat,Calendar)+java8新增日期API (LocalTime,LocalDate,LocalDateTime)
这篇文章介绍了Java中处理日期和时间的API,包括旧的日期API(Date、SimpleDateFormat、Calendar)和Java 8引入的新日期API(LocalTime、LocalDate、LocalDateTime)。文章详细解释了这些类/接口的方法和用途,并通过代码示例展示了如何使用它们。此外,还讨论了新旧API的区别,新API的不可变性和线程安全性,以及它们提供的操作日期时间的灵活性和简洁性。