日期时间
JDK8之前的日期时间API
1 java.lang.System中的currentTimeMillis()
public static long currentTimeMillis()
:返回当前时间与1970年1月1日0时0分0秒的毫秒差值。
2 java.util.Date
Date
类表示特定的时间时刻,精度为毫秒级。
常用的结构为两个构造器和两个方法:
构造器:
public Date()
:构造一个表示当前时间的Date
对象。public Date(long date)
:构造一个表示指定毫秒数(该毫秒数表示的与1970年1月1日的毫秒差)对应的时间的Date
对象。
方法:
public long getTime()
:返回对应Date
对象对应的与1970年1月1日的毫秒差值。public String toString()
:返回对应Date
对象对应的时间,显示的格式包括年、月、日、星期、小时、分钟、秒、时区。这也是直接打印对应Date
对象的返回值。
- 示例:
3 java.sql.Date
java.sql.Date
类是java.util.Date
的子类,是用于表示sql中date类型的数据对应的时间。
常用的结构包括一个构造器和一个方法:
构造器:
public Date(long date)
:构造指定毫秒数的java.sql.Date
对象,其中参数的毫秒数是自January 1, 1970, 00:00:00 GMT以来的毫秒数不超过8099年的毫秒数。负数表示从1970年过去某个时间到1970年1月1日00:00:00 GMT的毫秒数。
方法:
public String toString()
:返回对应java.sql.Date
对象表示的时间,格式为年-月-日
,也是打印对应java.sql.Date
对象的返回值。
- 示例:
java.util.Date
对象与java.sql.Date
对象的转换java.util.Date
对象转换为java.sql.Date
对象:他们之间的唯一联系就是都可以与毫秒数转换,因此,只要将对应java.util.Date
对象先转换为对应的毫秒数(getTime)方法,再作为java.sql.Date
对象的构造器的参数,即可完成对应转换。java.sql.Date
对象转换为java.util.Date
对象:由于java.sql.Date
为java.util.Date
的子类,因此可以直接通过多态转换。
4 java.text.SimpleDateFormat
SimpleDateFormat
类可以理解为,对Date
进行格式化和解析的类。
- 格式化:
Date
--->指定格式的String
; - 解析:指定格式的
String
--->Date
。
SimpleDateFormat
对象对应于针对某种格式的格式化和解析器,简单地说,SimpleDateFormat
对象只能针对其对应的格式进行格式化和解析。
SimpleDateFormat
实例化:
public SimpleDateFormat()
:默认空参构造器会构造一个针对默认格式的SimpleDateFormat
对象,可以通过查看格式化后的Date
对应的String
来查看默认格式。public SimpleDateFormat(String pattern)
:该构造器会根据指定的格式模式来构造指定格式的SimpleDateFormat
对象,常用的格式为yyyy-MM-dd hh:mm:ss
,设计格式模式具体参照官方文档。
格式化与解析方法:
public final String format(Date date)
:该方法能够格式化Date
对象为对应的格式的字符串。该方法是SimpleDateFormat
对象继承自抽象类java.text.DateFormat
的。public Date parse(String source)
:该方法能够将对应格式对应的字符串解析为对应的Date
对象。该方法也是SimpleDateFormat
对象继承自抽象类java.text.DateFormat
的。
示例:
- 默认格式:
- 指定格式:
5 Calendar
Calendar
是指java.util.Calendar
,实质上是一个抽象类,该类能够将特定时间与日历中的属性相互转换,如YEAR、MONTH、DAY of MONTH、HOUR等,并且能够设置日历属性。
该类的对象可以理解为一个具有对应时间的所有日历属性的结构,该类的对象能够通过其属性来间接地表示其对应的时间。
Calendar
对象的构建:
由于Calendar
是抽象类,没有直接对象,这里有两种方式创建Calendar
对象:
- 通过构建其子类
GregorianCalendar
的对象来实现Calendar
对象的创建。 - 通过使用
Calendar
的生成Calendar
对象的静态方法public static Calendar getInstance()
来实现Calendar
对象的创建,其本质上仍是GregorianCalendar
对象,只是该方法返回Calendar
对象。
推荐使用第二种方式来创建Calendar
对象,得到的Calendar
对象是一个具有当前时间的所有日历属性的结构,该类的对象能够通过其属性来间接地表示其对应的当前的时间。
Calendar
类对应的常用方法:
public abstract void add(int field, int amount)
:该方法能够对对应Calendar
对象对应的时间对应的指定属性增加或减少对应的量(减少就是amount为负数)。public int get(int field)
:该方法能够返回对应Calendar
对象对应的时间对应的指定的日历属性值,参数field
就是指定日历属性,直接通过传入Calendar
类的静态属性来实现,返回的int
型表示对应属性对应的值,可以通过查阅Calendar
类的静态属性对应的int
值来确定具体含义。public void set(int field, int value)
:该方法能够设置对应Calendar
对象对应的时间对应的指定的日历属性值。设置后也就改变了Calendar
对象对应的时间。public final Date getTime()
:该方法能够得到对应Calendar
对象对应的时间对应的Date
对象,相当于实现Calendar
--->Date
的转换。public final void setTime(Date date)
:该方法能够将Date
对象对应的时间转换为对应的Calendar
对象,相当于实现Date
--->Calendar
的转换。
Calendar
类对应的常用属性:
public static final int YEAR
:年的表示,即表示Calendar
对象对应的时间的年份。public static final int MONTH
:月的表示,注意一月对应的值为0,即表示Calendar
对象对应的时间的月份。public static final int DATE
:一个月中的天数表示,等同于DAY_OF_MONTH
,即表示Calendar
对象对应的时间的月份中的天数。public static final int DAY_OF_MONTH
:一个月中的天数表示,同上。public static final int DAY_OF_YEAR
:表示Calendar
对象对应的时间是这一年的第几天。DAY_OF_WEEK
:表示Calendar
对象对应的时间是这一周的第几天,默认周日是一周的第一天,即周日是1。public static final int DAY_OF_WEEK_IN_MONTH
:表示Calendar
对象对应的时间是在这个月的第几周。负数表示从月末开始数。public static final int WEEK_OF_MONTH
:表示Calendar
对象对应的时间是在这个月的第几周。public static final int WEEK_OF_YEAR
:表示Calendar
对象对应的时间是在这一年的第几周。public static final int HOUR
:表示Calendar
对象对应的时间在这一天的小时数,12进制。public static final int HOUR_OF_DAY
:同上,24进制。public static final int MINUTE
:表示Calendar
对象对应的时间在这一天这一小时的分钟数。public static final int SECOND
:表示Calendar
对象对应的时间在这一天这一小时这一分钟的秒数。public static final int MILLISECOND
:表示Calendar
对象对应的时间在这一天这一小时这一分钟的毫秒数。
示例:
JDK8中的日期时间API
JDK8之前的日期时间API使用起来并不够方便:
- 可变性:
Calendar
类对应的对象可以设置对应的时间的属性值,即修改对应的时间,但是这种修改体现出该类的可变
性,即对时间的修改就是修改原来的时间。
但是像日期和时间这样的数据,不可变
更合适,也就是说,只要改变,就应该是生成了对应的新的对象而不影响原来的时间对应的对象。 - 具有偏移量:
Calendar
对象的月份,一月对应的值是0,即每个月份对应的值是我们希望的值-1(不符合本地月份的值),另外,其显示的一周的天,周天是1,这也与我们希望的值不同。 - 格式化有限:格式化只针对
Date
,而不能对Calendar
进行格式化。 - 线程不安全,且不能处理闰秒。闰秒理解为自动更新调整时间以保持时间的一致性的秒数(因为地球自转等原因会使得时间会有偏差)。
JDK8中新增了本地化时间日期API,这些API大大简化了日期时间和本地化的管理:
java.time
:包含值对象的基础包;java.time.chrono
:提供对不同的日历系统的访问;java.time.format
:格式化和解析时间和日期;java.time.temporal
:包括底层框架和扩展特性;java.time.zone
:包含时区支持的类。
其中,比较常用的是:java.time
和java,format
,也可能会用到java.temporal
。
1 LocalDate & LocalTime & LocalDateTime
LocalDate, LocalTime, LocalDateTime
是java.time
中的三个类,这三个类非常类似。
LocalDate
表示的是ISO-8601日历系统中没有时区的日期,如2007-12-03。LocalDate
表示的是不可变的日期对象,其仅表示日期,一般格式为:年-月-日
,可以获取对应日期对应的其他属性值,比如day-of-year, day-of-week and week-of-year。LocalDate
是不可变的,并且是线程安全的。LocalTime
表示的是ISO-8601日历系统中没有时区的时间,如10:15:30。LocalTime
表示的是不可变的时间对象,其仅表示时间,一般格式为:时:分:秒
,其表示的时间是纳秒精度的,因此纳秒精度的时间可以构建为该对象,也可以获取对应时间对应的其他属性,比如hour, minute, second, Nano。LocalTime
也是不可变的,并且是线程安全的。LocalDateTime
表示的是ISO-8601日历系统中没有时区的日期和时间,如2007-12-03T10:15:30。LocalDateTime
可以理解为LocalDate
和LocalTime
的结合,可以获取对应日期和时间的其他属性(就是LocalDate和LocalTime的属性结合)。LocalDateTime
也是不可变的,并且是线程安全的。
ISO-8601日历系统是国家标准化组织制定的现代公民的日期和时间表示法,也就是公历。
LocalDate & LocalTime & LocalDateTime的实例化
上述三个类的实例化都是主要使用对应的两个静态方法:
now()
:该方法会返回一个当前日期或时间或日期和时间的对应类对象。of(argument)
:该方法会返回指定日期或时间或日期和时间的对应类对象。
示例:
LocalDate & LocalTime & LocalDateTime的方法
三个类对应的方法类似,区别仅在于针对日期或时间或日期和时间,简单地说,LocalDateTime
对应的方法就是前两者的结合,前两者有的它都有。
根据方法的功能主要分为四类:获取其他属性值getField()
、增加对应属性值plusField()
、减少对应属性值minusField()
、设置对应属性值withField()
。注意,只要改变都会返回新的对应的对象,体现不可变性。
LocalDate:
- 获取其他属性值,其中返回值为某个类时,表示返回对应的表示对应时间的枚举类对象,可以理解为返回对应的
String
: - 增加对应属性值,生成新的对应对象:
- 减少对应的属性值,生成新的对应对象:
- 设置对应的属性值,生成新的对应对象:
- 获取其他属性值,其中返回值为某个类时,表示返回对应的表示对应时间的枚举类对象,可以理解为返回对应的
LocalTime:
- 获取其他属性值:
- 增加对应属性值,生成新的对应对象:
- 减少对应的属性值,生成新的对应对象:
- 设置对应的属性值,生成新的对应对象:
- 获取其他属性值:
LocalDateTime:
- 获取其他属性值,其中返回值为某个类时,表示返回对应的表示对应时间的枚举类对象,可以理解为返回对应的
String
: - 增加对应属性值,生成新的对应对象:
- 减少对应的属性值,生成新的对应对象:
- 设置对应的属性值,生成新的对应对象:
- 获取其他属性值,其中返回值为某个类时,表示返回对应的表示对应时间的枚举类对象,可以理解为返回对应的
示例:
2 Instant
Instant
是指java.time.Instant
类,是表示面向机器的时间的类。类似于Date
类。
Instant
对象是表示时间线上的一个瞬时点,准确地说,是表示从1970年1月1日(UTC)开始的秒数,以毫秒为单位。这可能被用来记录应用程序中的事件时间戳。Instant
类中有静态属性EPOCH
来专门表示1970年1月1日(UTC)的时间,对于Instant
,EPOCH
之后的瞬时点是正数(long型),EPOCH
之前的瞬时点是负数(long型)。
Instant
是不可变的,且线程安全的。
1) 关于时间的基本常识
秒、毫秒、微秒、纳秒的换算
- 1s = 1000ms
- 1ms = 1000us
- 1us = 1000ns
- 时区
由于地球自转,地球上每个地区面向太阳和背向太阳的时刻各不相同,1884年国际子午线会议将地球分为24个区域,每个区域相差15个经度,从0°经线所在的零时区开始,向东和向西各有12个时区,中国北京就是东八区。
以零时区为标准,向东每跨一个时区就是增加一小时,向西每跨一个时区就是减一小时。例如零时区为早上八点,那么东八区就是下午四点,而西一区就是早上七点。
时间标准
UTC(世界标准时间)
:UTC:协调世界时,又称 世界标准时间或世界协调时间,简称 UTC,是最主要的世界时间标准。其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间。GMT(格林尼治时间)
:格林尼治平时,又称 格林尼治平均时间或格林尼治标准时间,简称 GMT,是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。
理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间。由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能与实际的太阳时有误差,最大误差达16分钟。
由于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治时间已经不再被作为标准时间使用。现在的标准时间,是由原子钟报时的协调世界时(UTC)CST(北京时间)
:北京时间,又称 中国标准时间。在时区划分上,属东八区,比协调世界时早 8 小时,记为:UTC+8
2) Instant
实例化
public static Instant now()
:获得表示以UTC为标准的当前时间点的Instant
对象。public static Instant ofEpochMilli(long epochMilli)
:获得表示指定毫秒数对应的时间点的Instant
对象。
3) Instant
方法
public OffsetDateTime atOffset(ZoneOffset offset)
:对对应Instant
对象对应的时间点添加偏移量以生成对应的新的时间点的对象。public long toEpochMilli()
:返回对应Instant
对象对应的时间点对应的毫秒数。
3 DateTimeFormatter
DateTimeFormatter
是指java.time.format.DateTimeFormatter
类,其类似于SimpleDateFormat
类,是一个对表示日期或时间或日期和时间对象的格式化和解析器。
SimpleDateFormat
类针对的是Date
对象。DateTimeFormatter
类针对的是TemporalAccessor
对象。而TemporalAccessor
是一个接口,其典型实现类包括LocalDate, LocalTime, LocalDateTime
等。因此,可以说DateTimeFormatter
类针对的是LocalDate, LocalTime, LocalDateTime
对象的格式化的类。
之所以没有强调其解析的作用,是因为,该类解析结果虽然是TemporalAccessor
对象,但并不是LocalDate, LocalTime, LocalDateTime
对象,而是Parsed
对象。
DateTimeFormatter
类与SimpleDateFormat
类类似,每个对象是针对对应的一种格式来进行格式化和解析的。
1) DateTimeFormatter
实例化DateTimeFormatter
实例化涉及格式的指定,根据能够指定的格式类型,可以通过三种方式实现DateTimeFormatter
实例化:
- 使用
DateTimeFormatter
类中提供的标准格式:DateTimeFormatter
类中提供了标准格式对应的DateTimeFormatter
对象,可以直接使用,具体可参照官方文档。 使用
DateTimeFormatter
类中提供的本地格式:DateTimeFormatter
类中提供了生成本地格式的对应对象方法,对应方法需要指定本地格式的样式,该样式是定义在FormatStyle
的枚举类中,其中提供了FULL, LONG, MEDIUM, SHORT
四种样式。注意对于DateTime
不存在FULL
样式,即不能指定FULL
样式的DateTime
的本地格式,会报错。public static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle)
:创建指定日期样式的本地日期对应的DateTimeFormatter
对象。public static DateTimeFormatter ofLocalizedTime(FormatStyle timeStyle)
:创建指定时间样式的本地时间对应的DateTimeFormatter
对象。public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateTimeStyle)
:创建指定日期样式的本地日期和时间对应的DateTimeFormatter
对象。public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle)
:创建指定日期和时间样式的本地日期和时间对应的DateTimeFormatter
对象。
使用自定义的格式:
DateTimeFormatter
类中提供了生成自定义格式的对应对象方法,对应方法需要指定自定义的格式模式字符串,如uuuu-MM-dd HH:mm:ss
。如何自定义具体参照官方文档。public static DateTimeFormatter ofPattern(String pattern)
:创建指定自定义格式的DateTimeFormatter
对象。
2) 格式化和解析
类似于SimpleDateFormat
对象,格式化使用对应的format()
方法,解析使用对应的parse()
方法:
public String format(TemporalAccessor temporal)
public TemporalAccessor parse(CharSequence text)
3) 示例
- 标准格式:
本地格式:
- 日期:
- 时间:
- 日期和时间:
- 日期:
- 自定义格式:
4 其他API
这里列举的最后两个是在java.time.temporal
中,其他都是在java.time
中。
JDK8之前与之后日期时间类的转换: