时间的统一标准
时间的两种统一标准主要是格林威治时间(GMT)和协调世界时(UTC)。
格林威治时间(GMT)
- 定义:GMT全称为Greenwich Mean Time,即格林威治平时(也称格林威治时间)。它规定太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间为中午12点。(太阳直射零度经线)
- 历史背景:格林威治皇家天文台为了海上霸权的扩张计划,在十七世纪就开始进行天体观测。为了天文观测,选择了穿过英国伦敦格林威治天文台子午仪中心的一条经线作为零度参考线,即格林威治子午线。1884年10月,在美国华盛顿召开的国际子午线会议将格林威治子午线设定为本初子午线,并将格林威治平时(GMT)作为世界时间标准(UT, Universal Time)。本初子午线作为零度经线,往右为东,往左为西,各划分了八个时区,每往东增加一个时区,时间增加一个小时,每往西增加一个时区,时间减少一个小时,我国处于东八区,因此我国的时间要在格林威治时间的基础上增加8个小时。
- 现状:1972年之前,GMT一直是世界时间的标准。然而,随着技术的发展和对时间精度的更高要求,GMT逐渐被UTC所取代。但在日常生活中,尤其是在不需要精确到秒的情况下,GMT仍然被广泛使用,并与UTC视为等同。
协调世界时(UTC)
- 定义:UTC全称为Coordinated Universal Time,即协调世界时,又称世界统一时间、世界标准时间、国际协调时间。UTC是经过平均太阳时(以GMT为准)、地轴运动修正后的新时标以及以秒为单位的国际原子时所综合精算而成的时间。
原子钟:利用铯原子震动的频率计算出的时间,铯原子震动9,192,631,770次视为经过1秒。
- 历史背景:UTC的概念最早在1960年由国际无线电咨询委员会规范统一,并在次年投入实际使用。而“Coordinated Universal Time”这个名字则在1967年才被正式采纳。UTC的计算过程相当严谨精密,其误差值必须保持在0.9秒以内。若大于0.9秒,则由位于巴黎的国际地球自转事务中央局发布闰秒,以使UTC与地球自转周期一致。
- 现状:UTC是现在全球通用的时间标准,全球各地都同意将各自的时间进行同步协调。在军事中,协调世界时会使用“Z”来表示,而在无线电联络中则使用“Zulu”作为代称。
综上所述,GMT和UTC是时间的两种主要统一标准。虽然GMT在历史上曾作为世界时间的标准,但如今UTC以其更高的精度和全球范围内的广泛应用成为了现代社会的首选时间标准。
JDK8以前的日期时间类
日期工具类:Date
date是JDK编写好的一个JavaBean类,用来描述日期与时间,精确到毫秒。
获取日期对象
1. 空参构造
使用空参构造方法创建日期对象,获取到的是当前操作系统的时间。
这个方法在底层调用了System工具类的currentTimeMillis方法,获取当前时间与时间原点之间的毫秒值,再进行计算与格式化输出为日期。
2.带参构造
public Date(long time)
指定一个毫秒值,从时间原点开始,计算这个毫秒值对应的日期。注意:如果传入的毫秒值为负数,会获得对应的1970年之前的日期。
常用方法
1.public void setTime(long time):修改日期对象的时间
2.public long getTime():获取当前时间所对应的毫秒值。此方法可以用于计算。
日期格式化:SimpleDateFormat
date类虽然能表示时间,但是它的输出格式不是大众所熟悉的。
SimpleDateFormat类可以将Date类型的日期数据输出为指定格式的日期。 还可以将字符串形式的日期解析为Date类型的变量
模式
使用SimpleDateFormat类格式化时间,需要指定一个时间模式,类似于正则表达式,它的作用就是告诉该类你期望的日期的输出格式,模式pattern由标识符和间隔符组成,标识符用来对应日期数据,就像正则表达式种/w表示数字、大小写字符以及下划线。
Letter Date or Time Component Presentation Examples G
Era designator Text AD
y
Year Year 1996
;96
Y
Week year Year 2009
;09
M
Month in year (context sensitive) Month July
;Jul
;07
L
Month in year (standalone form) Month July
;Jul
;07
w
Week in year Number 27
W
Week in month Number 2
D
Day in year Number 189
d
Day in month Number 10
F
Day of week in month Number 2
E
Day name in week Text Tuesday
;Tue
u
Day number of week (1 = Monday, ..., 7 = Sunday) Number 1
a
Am/pm marker Text PM
H
Hour in day (0-23) Number 0
k
Hour in day (1-24) Number 24
K
Hour in am/pm (0-11) Number 0
h
Hour in am/pm (1-12) Number 12
m
Minute in hour Number 30
s
Second in minute Number 55
S
Millisecond Number 978
z
Time zone General time zone Pacific Standard Time
;PST
;GMT-08:00
Z
Time zone RFC 822 time zone -0800
X
Time zone ISO 8601 time zone -08
;-0800
;-08:00
常用方法
1、public SimpleDateFormat():空参构造,这种方法构造的实例使用默认的模式
2、public SimpleDateFormat(String pattern):带参构造,使用指定的模式
3、public final String format(Date date) :格式化(date -->String)
4、public Date parse(String source) throws ParseException:解析(String-->Date)
日历类:Calendar
顾名思义,这个类的作用是年在月日的量级上对日期和时间进行获取与修改。
获取日历对象
在JDK中,Calendar被定义为一个抽象类,无法直接通过构造方法创建实例。 在Calendar类中有一个静态方法是专门创建Calendar实例的。
public static Calendar getInstance(),该方法调用Calendar中的CreateCalendar,根据当前系统的时区信息,从Calendar的三个子类BuddhistCalendar、JapaneseImperialCalendar和GregorianCalendar中选择一个,以多态的方式,为Calendar创建实例,其中,最常用的是GregoriaCalendar,即格林威治日历。通过这种方式创建的Calendar实例,储存当前时间的日历信息。
所以,Calendar的实例实质的是它的子类的实例,而不是它本身。
细节:
- 日历类在其内部,通过一个数组来存储时区、纪元、年、月、日等字段信息的。
- 日历类内部,月份的范围是0~11,在此基础上加1才是真实的月份
- 日历类内部,一周中的天数范围是1~7,但是一个星期的第一天被认为是星期天,因此数字1对应星期天,以此类推。
常用方法
1、public final Date getTime() 用日历对象获取日期类实例
2、public final void setTime(Date date) 用日期对象给日历对象赋值
3、public long getTimeInMillis() 获取时间毫秒值
4、public void setTimeInMillis(long millis) 用时间毫秒值给日历实例赋值
5、public int get(int field) 获取日历对象的字段信息
在这个方法中,field
参数实际上是内部数组中的索引,该方法通过索引访问内部日期信息数组来获取对应的数据。但是这样不好理解,因此Calendar
类提供了一系列常量来帮助理解字段与它们对应的整数值之间的关系。这些常量是在Calendar
类中定义的静态变量,每个变量都代表了一个特定的日历字段,并且每个字段都有一个唯一的整数值与之对应。例如:
这些常量是Calendar
类的一部分,用于在Java程序中处理时间和日期。通过使用这些常量,你可以轻松地访问和修改Calendar
对象中的特定字段。
-
YEAR - 表示年份。这是四位数的年份,例如2023。
-
MONTH - 表示月份。需要注意的是,这个字段的值是从0开始的,即0代表1月,1代表2月,依此类推,直到11代表12月。
-
DAY_OF_MONTH 或 DATE - 表示月份中的天数,即一个月的第几天。值的范围从1到该月的天数(可能是28、29、30或31,取决于月份和是否是闰年)。
-
HOUR_OF_DAY - 表示一天中的小时数(0-23)。这与12小时制的小时数不同,后者需要上午/下午的指示。
-
HOUR - 在12小时制中,这表示上午或下午的小时数(0-11)。要确定是上午还是下午,通常需要查看
AM_PM
字段。 -
MINUTE - 表示小时中的分钟数(0-59)。
-
SECOND - 表示分钟中的秒数(0-59)。对于大多数用途,这足以表示时间,但在需要更高精度时,可以使用
MILLISECOND
字段。 -
MILLISECOND - 表示秒中的毫秒数(0-999)。这对于需要高精度时间计量的应用程序非常有用。
-
DAY_OF_WEEK - 表示一周中的天数,其中周日=1,周一=2,依此类推,直到周六=7。
-
DAY_OF_YEAR - 表示一年中的天数(1-365或366,取决于是否是闰年)。
-
WEEK_OF_YEAR - 表示一年中的周数。这个字段的计算方式可能因地区而异,因为不同的文化可能有不同的周和年的开始方式。
-
WEEK_OF_MONTH - 表示一个月中的周数。同样,这个字段的计算也可能因地区而异。
-
AM_PM - 表示上午(0)或下午(1)。这个字段通常与
HOUR
字段一起使用,以表示12小时制的时间。 -
ERA - 表示纪元。在大多数情况下,这个字段用于区分公元前(BC)和公元后(AD)的时间。在格里高利历中,AD的值是1,而BC的值是0,但请注意,不是所有的历法都使用这种表示方式。
6、public void set(int field, int value) 修改日历实例的某个字段
7、public void add(int field, int amount) 增加或减少日历对象某字段的值,amount正增负减
注意:在Calendar中,各个字段是联动的,而不是孤立的,如果月份超过12,年数会增加一年,天数超过7,周数也会增加一周。
JDK8之后的日期相关类
比较:
jdk8之前,时间的计算和比较以时间戳为基础,代码写起来麻烦。
jdk8之后代码简单。
jdk8之前日期与时间相关类的实例可变,容易暴露问题,jdk8之后的日期与时间相关类实例不可变,安全。
Date相关
ZoneId:时区类
顾名思义,ZoneId类表示时区
常用方法
- public static Set<String> getAvailableZoneIds() 获取Java支持的所有时区,600个。
- public static ZoneId systemDefault() 获取当前系统时区
-
public static ZoneId of(String zoneId) 指定时区
Instant:时刻类
Instant,用于描述某一时刻,即时间戳的类
常用方法
- public static Instant now()
Instant类不能直接用构造方法创建实例,而是用静态方法now获取当前时刻的实例,这个实例表示当前的协调世界时,不带时区。输出格式为:2024-08-15T12:57:58.747Z
- public static Instant ofEpochMilli(long epochMilli) 根据指定的毫秒值,创建对应的时刻实例
- public static Instant ofEpochSecond(long epochSecond) 根据指定秒值,创建对应的时刻实例
- public static Instant ofEpochSecond(long epochSecond, long nanoAdjustment) 根据指定的秒和纳秒的值,创建对应的时刻实例
- public ZoneDateTime atZone(ZoneID zoneId) 根据指定的时区,和调用者代表的时刻,创建带时区的ZoneDateTime实例,即带有时区的时刻
- public boolean isBefore(Instant otherInstant) 判断调用者是否在参数之前
- public boolean isAfter(Instant otherInstant) 判断调用者是否在参数之后
-
public Instant minusMillis(long millisToSubtract) 用当前的时刻值减去指定的毫秒值获得新的时刻实例。
-
public Instant minusSeconds(long secondsToSubtract) 用当前的时刻值减去指定的秒值获得新的时刻实例。
-
public Instant minusNano(long nanosToSubtract) 用当前的时刻值减去指定的纳秒值获得新的时刻实例。
- public Instant plusMillis(long millisToAdd) 用当前时刻值加上指定的毫秒值获得新的时刻实例。
- public Instant plusSeconds(long secondsToAdd) 用当前时刻值加上指定的秒值获得新的时刻实例。
- public Instant plusNano(long nanosToAdd) 用当前的时刻值加上指定的纳秒值获得新的时刻实例。
ZoneDateTime:带时区的时间类
常用方法
- public static ZoneDateTime now() 获取当前的带时间时区实例
- public static ZonedDateTime of(int year, int month, int dayOfMonth,int hour, int minute, int second, int nanoOfSecond, ZoneId zone) 根据指定的各个时间相关字段创建带时区的时间实例
- public static ZoneDateTime ofInstant(Instant instant,ZoneId zone) 根据指定的Instant实例和ZoneId实例创建ZoneDateTime实例
- withXxx(xxx) 修改时间相关字段的系列方法
- minusXxx(x) 减少时间相关字段的系列方法
- plusXxx(x) 增加时间相关字段的系列方法
SimpleDateFormat相关
DateTimeFormatter:日期格式化类
类似于simpleDateFormat
常用方法
-
public static DateTimeFormatter ofPattern(String pattern):获取日期格式化类的实例
-
String format(时间对象) 按照指定方法格式化