# Java 日期类
Java 日期类主要包括 java.util.Date 、 java.util.Calendar 和 java.time 包下的类。
java.util.Date 类是 Java 提供的最早的日期类,它表示自 1970 年 1 月 1 日 0 时 0 分 0 秒 (GMT) 起的毫秒数。但是它的设计存在缺陷,所以在 Java 8 之后,推荐使用 java.time 包下的日期类。
java.util.Calendar 类是一个抽象类,提供了一些基本的日期操作,比如获取某一时间的年、月、日、时、分、秒等。但是该类使用起来比较繁琐。
Java 8 之后推出了全新的日期时间 API , java.time 包下的类,包括 LocalDate 、 LocalTime 、 LocalDateTime 、 ZonedDateTime 等,这些类提供了更简单易用的方法和更好的可读性,能够更方便地进行日期和时间的计算和格式化。
下面是一些常用的 Java 日期类的方法:
# Date
Date():创建一个表示当前时间的 Date 对象。getTime():返回自 1970 年 1 月 1 日 0 时 0 分 0 秒 (GMT) 起的毫秒数。toString():返回一个 String 类型的表示形式,格式为EEE MMM dd HH:mm:ss zzz yyyy。
# Calender
getInstance():返回一个 Calendar 对象,表示当前时间。get(int field):获取指定的日期字段值,如Calendar.YEAR、Calendar.MONTH、Calendar.DAY_OF_MONTH等。set(int field, int value):设置指定的日期字段值。getTime():返回一个 Date 对象,表示当前时间。
# JDK8 新增的日期类
Java 8 中引入了 java.time 包,该包提供了一组全新的日期和时间 API,其中包括 LocalDate 、 LocalDateTime 、 ZonedDateTime 等类,它们比旧的 java.util.Date 和 java.util.Calendar 更加方便易用,同时也更加安全和健壮。
以下是 LocalDate 、 LocalDateTime 的详细介绍:
# LocalDate
LocalDate 表示一个日期,不包含时间和时区信息。它可以用来表示一个生日、节日、合同签订日期等等。
创建 LocalDate 对象有多种方式,比如使用 now() 方法获取当前日期,或者使用 of() 方法指定年、月、日:
LocalDate today = LocalDate.now(); | |
LocalDate date = LocalDate.of(2023, 2, 24); |
我们可以通过 getYear() 、 getMonth() 、 getDayOfMonth() 等方法获取日期的年、月、日等信息:
int year = date.getYear(); | |
int month = date.getMonthValue(); | |
int day = date.getDayOfMonth(); |
LocalDate 还提供了很多方法,比如 plusDays() 、 minusMonths() 等,用于对日期进行加减操作。例如:
LocalDate tomorrow = today.plusDays(1); | |
LocalDate previousMonthSameDay = today.minusMonths(1); |
LocalDate 也支持一些常用的比较方法,比如 isBefore() 、 isAfter() 、 isEqual() ,用于比较两个日期的先后顺序:
boolean isBefore = today.isBefore(tomorrow); | |
boolean isAfter = today.isAfter(previousMonthSameDay); | |
boolean isEqual = today.isEqual(date); |
# LocalDateTime
LocalDateTime 表示一个日期时间,不包含时区信息。它可以用来表示一个会议时间、发布时间、交易时间等等。
创建 LocalDateTime 对象有多种方式,比如使用 now() 方法获取当前日期时间,或者使用 of() 方法指定年、月、日、时、分、秒等:
LocalDateTime now = LocalDateTime.now(); | |
LocalDateTime dateTime = LocalDateTime.of(2023, 2, 24, 10, 30, 0); |
我们可以通过 getYear() 、 getMonth() 、 getDayOfMonth() 、 getHour() 、 getMinute() 、 getSecond() 等方法获取日期时间的年、月、日、时、分、秒等信息:
int year = dateTime.getYear(); | |
int month = dateTime.getMonthValue(); | |
int day = dateTime.getDayOfMonth(); | |
int hour = dateTime.getHour(); | |
int minute = dateTime.getMinute(); | |
int second = dateTime.getSecond(); |
LocalDateTime 类是 Java 8 中的日期时间类,表示日期和时间,不带时区信息。下面是 LocalDateTime 类中常用的一些方法:
now():获取当前日期时间。
LocalDateTime now = LocalDateTime.now(); |
of():根据指定的年、月、日、时、分、秒、毫秒等参数创建一个LocalDateTime实例。
LocalDateTime dateTime = LocalDateTime.of(2022, 3, 1, 12, 30, 0); |
plusXxx():在当前LocalDateTime的基础上增加指定的时间量,其中 Xxx 可以是Years、Months、Weeks、Days、Hours、Minutes、Seconds等。
LocalDateTime dateTime = LocalDateTime.now(); | |
LocalDateTime plusOneDay = dateTime.plusDays(1); |
minusXxx():在当前LocalDateTime的基础上减少指定的时间量,其中 Xxx 可以是Years、Months、Weeks、Days、Hours、Minutes、Seconds等。
LocalDateTime dateTime = LocalDateTime.now(); | |
LocalDateTime minusOneHour = dateTime.minusHours(1); |
getXxx():获取LocalDateTime的指定部分,其中 Xxx 可以是Year、Month、DayOfMonth、DayOfWeek、DayOfYear、Hour、Minute、Second、NanoOfSecond等。
LocalDateTime dateTime = LocalDateTime.now(); | |
int year = dateTime.getYear(); | |
Month month = dateTime.getMonth(); | |
int dayOfMonth = dateTime.getDayOfMonth(); | |
DayOfWeek dayOfWeek = dateTime.getDayOfWeek(); | |
int hour = dateTime.getHour(); | |
int minute = dateTime.getMinute(); | |
int second = dateTime.getSecond(); | |
int nano = dateTime.getNano(); |
withXxx():设置LocalDateTime的指定部分,其中 Xxx 可以是Year、Month、DayOfMonth、DayOfWeek、DayOfYear、Hour、Minute、Second、NanoOfSecond等。
LocalDateTime dateTime = LocalDateTime.now(); | |
LocalDateTime withYear2023 = dateTime.withYear(2023); |
isXxx():判断LocalDateTime的指定部分是否满足某个条件,其中 Xxx 可以是LeapYear、After、Before等。
LocalDateTime dateTime = LocalDateTime.now(); | |
boolean isLeapYear = dateTime.toLocalDate().isLeapYear(); |
toXxx():将LocalDateTime转换为其他日期时间类,其中 Xxx 可以是LocalDate、LocalTime、Instant等。
LocalDateTime dateTime = LocalDateTime.now(); | |
LocalDate date = dateTime.toLocalDate(); | |
LocalTime time = dateTime.toLocalTime(); | |
Instant instant = dateTime.toInstant(ZoneOffset.UTC); |
这些是 LocalDateTime 类中比较常用的方法,可以方便地对日期时间进行操作和计算。
# Instant
Java 的 Instant 类是用来表示时刻的类,可以精确到纳秒级别。它是不可变的,线程安全的。 Instant 类是在 Java 8 中引入的,它提供了与时区无关的机制来处理日期和时间。
Instant 类的实例可以从时钟获取当前时间,也可以从另一个 Instant 实例中创建,或者通过解析表示 ISO-8601 格式的字符串来创建。 Instant 类的 API 提供了许多方法来操作 Instant 实例,以下是一些常用方法:
now():获取当前时间戳的Instant实例。
Instant now = Instant.now(); |
ofEpochSecond():根据秒数创建Instant实例。
Instant instant = Instant.ofEpochSecond(1614305156); |
ofEpochMilli():根据毫秒数创建Instant实例。
Instant instant = Instant.ofEpochMilli(1614305156000L); |
getEpochSecond():获取秒数。
long epochSecond = instant.getEpochSecond(); |
getNano():获取纳秒数。
int nano = instant.getNano(); |
plusSeconds():添加指定的秒数。
Instant newInstant = instant.plusSeconds(10); |
minusSeconds():减去指定的秒数。
Instant newInstant = instant.minusSeconds(10); |
isAfter():判断是否在指定的 Instant 实例之后。
boolean isAfter = instant.isAfter(anotherInstant); |
isBefore():判断是否在指定的Instant实例之前。
boolean isBefore = instant.isBefore(anotherInstant); |
toString():将Instant实例转换为字符串。
String str = instant.toString(); |
总之, Instant 类提供了一种简单而灵活的方式来处理日期和时间,它适用于需要精确处理时间戳的应用程序。
# Timestamp
Java 中的 Timestamp 类是用于处理数据库中日期时间类型的类,继承自 java.util.Date 类,但是它的精度要高于 Date 类,可以精确到纳秒级别。 Timestamp 类在 JDBC 程序中很常用,它可以表示精确到秒的时间戳。
Timestamp 类的构造方法有以下几种:
Timestamp(long time):根据指定的时间创建一个Timestamp对象。Timestamp(String s):根据字符串表示的时间创建一个Timestamp对象。Timestamp(int year, int month, int date, int hour, int minute, int second, int nano):根据指定的年、月、日、时、分、秒和纳秒数创建一个Timestamp对象。
Timestamp 类中的常用方法包括:
getTime():返回以毫秒表示的Timestamp值。valueOf(String s):将指定的字符串转换为Timestamp类型。valueOf(LocalDateTime dateTime):将指定的LocalDateTime转换为Timestamp类型。toLocalDateTime():将Timestamp对象转换为LocalDateTime对象。compareTo(Timestamp ts):比较两个Timestamp对象的大小。equals(Object ts):判断当前Timestamp对象是否与指定对象相等。toString():将Timestamp对象转换为字符串表示。setNanos(int n):设置Timestamp对象的纳秒数。setYear(int year):设置Timestamp对象的年份。setMonth(int month):设置Timestamp对象的月份。setDate(int date):设置Timestamp对象的日期。setHours(int hours):设置Timestamp对象的小时。setMinutes(int minutes):设置Timestamp对象的分钟。setSeconds(int seconds):设置Timestamp对象的秒数。
总之, Timestamp 类是 Java 中处理时间戳的一个重要类,它可以很方便地将时间戳转换为日期时间类型,或者将日期时间类型转换为时间戳。在开发中,我们通常会使用 Timestamp 来操作数据库中的时间类型数据。
# Locale
Java 中的 Locale 类表示了特定地理、政治或文化区域的信息,比如国家、语言、货币等。通过 Locale 类,Java 程序可以获取与地区相关的信息,例如日期和时间格式、货币符号、语言环境等。 Locale 类的实例表示一个特定的地理、政治或文化区域,由语言代码和国家(或地区)代码组成,例如 “en_US” 表示美国英语环境。
Locale 类提供了多个构造函数和静态方法,用于创建和获取特定的地理、政治或文化区域。常用的构造函数和方法包括:
Locale(String language)通过指定的语言代码创建一个Locale实例,国家代码默认为 ""。Locale(String language, String country)通过指定的语言代码和国家代码创建一个Locale实例。Locale(String language, String country, String variant)通过指定的语言代码、国家代码和变量创建一个Locale实例。Locale.getDefault()获取当前默认的Locale实例。Locale.getAvailableLocales()获取所有可用的Locale实例。getCountry()获取Locale实例的国家代码。getLanguage()获取Locale实例的语言代码。getDisplayName()获取Locale实例的显示名称。getDisplayName(Locale inLocale)获取在指定 Locale 环境下的Locale实例的显示名称。
Locale 类的应用场景包括但不限于以下几种:
- 本地化日期、时间、货币等格式
- 国际化应用程序的开发
- 区域性数据的处理
- 多语言文本的翻译和处理
# Zone 相关的类
在 Java 中,关于时区的相关操作主要是通过 java.time.Zone 相关的类来完成的。
首先, ZoneId 类表示了一个时区标识符,可以使用 ZoneId.of() 方法来获取。比如,以下代码可以获取表示 "Asia/Shanghai" 时区的 ZoneId :
ZoneId zoneId = ZoneId.of("Asia/Shanghai"); |
ZoneOffset 类表示了一个以秒为单位的时间偏移量,可以使用 ZoneOffset.ofTotalSeconds() 方法来获取。比如,以下代码可以获取表示东八区的 ZoneOffset :
ZoneOffset offset = ZoneOffset.ofTotalSeconds(8 * 3600); |
ZonedDateTime 类表示了一个带时区的日期和时间。可以使用 ZonedDateTime.of() 方法来创建一个 ZonedDateTime 对象。比如,以下代码可以创建表示当前时间在东八区的 ZonedDateTime :
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai")); |
另外,Java 还提供了一些方便的方法来进行时区转换。比如, LocalDateTime 可以使用 atZone() 方法将其转换为 ZonedDateTime ,然后使用 withZoneSameInstant() 方法将其转换为另一个时区的 ZonedDateTime :
LocalDateTime localDateTime = LocalDateTime.now(); | |
ZonedDateTime shanghaiTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai")); | |
ZonedDateTime newYorkTime = shanghaiTime.withZoneSameInstant(ZoneId.of("America/New_York")); |
类似的, Instant 可以使用 atZone() 方法将其转换为 ZonedDateTime ,然后使用 toInstant() 方法将其转换为 Instant :
Instant instant = Instant.now(); | |
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai")); | |
Instant newYorkTime = zonedDateTime.toInstant(); |
最后,需要注意的是,在处理时区相关的操作时,一定要注意时间的格式化和解析。比如,在使用 SimpleDateFormat 进行时间格式化时,应该使用带时区的格式化器来避免时区转换时的问题。
# 日期格式化
在 Java 中,可以使用格式化来将日期对象格式化为字符串。Java 提供了两种格式化方式:
- 使用
java.text.SimpleDateFormat类,该类可以根据指定的格式将日期格式化为字符串。
例如,下面的代码将 Date 对象格式化为字符串:
import java.text.SimpleDateFormat; | |
import java.util.Date; | |
public class DateFormatExample { | |
public static void main(String[] args) { | |
Date now = new Date(); | |
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String strDate = dateFormat.format(now); | |
System.out.println(strDate); | |
} | |
} |
输出结果:
2022-08-22 16:32:11 |
- 使用
java.time.format.DateTimeFormatter类,该类是 Java 8 新引入的日期时间格式化类,使用方式类似于SimpleDateFormat。
例如,下面的代码将 LocalDateTime 对象格式化为字符串:
import java.time.LocalDateTime; | |
import java.time.format.DateTimeFormatter; | |
public class DateTimeFormatterExample { | |
public static void main(String[] args) { | |
LocalDateTime now = LocalDateTime.now(); | |
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |
String strDate = now.format(formatter); | |
System.out.println(strDate); | |
} | |
} |
输出结果:
2022-08-22 16:32:11 |
需要注意的是,在使用 DateTimeFormatter 格式化 java.time 包中的日期时间类时,要使用对应的格式化模式,例如年份用大写的 yyyy 表示,月份用小写的 mm 表示等。
另外,如果需要将字符串转换为日期对象,可以使用 SimpleDateFormat 或 DateTimeFormatter 中的 parse 方法,例如:
String strDate = "2022-08-22 16:32:11"; | |
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
Date date = dateFormat.parse(strDate); |
或者
String strDate = "2022-08-22 16:32:11"; | |
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |
LocalDateTime dateTime = LocalDateTime.parse(strDate, formatter); |
需要注意的是,在使用 SimpleDateFormat 解析日期字符串时,要使用与格式化模式相同的模式进行解析。而使用 DateTimeFormatter 时,可以根据需要指定格式化模式。
# 日期类的相互转化
在 Java 中,我们可以使用各种日期类进行日期的操作。这些日期类包括 java.util.Date 、 java.sql.Date 、 java.util.Calendar 、 java.time.LocalDate 、 java.time.LocalDateTime 、 java.time.Instant 等。为了进行不同日期类之间的相互转化,Java 提供了一些方法。
下面是一些常见的日期类之间的转化方法:
java.util.Date和java.sql.Date的转化将
java.util.Date转换成java.sql.Date:java.util.Date date = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(date.getTime());
将
java.sql.Date转换成java.util.Date:java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
java.util.Date date = new java.util.Date(sqlDate.getTime());
java.util.Date和java.time.LocalDateTime的转化将
java.util.Date转换成java.time.LocalDateTime:java.util.Date date = new java.util.Date();
Instant instant = date.toInstant();
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
将
java.time.LocalDateTime转换成java.util.Date:LocalDateTime localDateTime = LocalDateTime.now();
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
java.util.Date date = java.util.Date.from(instant);
java.util.Calendar和java.time.LocalDateTime的转化将
java.util.Calendar转换成java.time.LocalDateTime:Calendar calendar = Calendar.getInstance();
LocalDateTime localDateTime = LocalDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());
将
java.time.LocalDateTime转换成java.util.Calendar:LocalDateTime localDateTime = LocalDateTime.now();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
java.util.Date和java.time.Instant的转化将
java.util.Date转换成java.time.Instant:java.util.Date date = new java.util.Date();
Instant instant = date.toInstant();
将
java.time.Instant转换成java.util.Date:Instant instant = Instant.now();
java.util.Date date = java.util.Date.from(instant);
java.util.Date和java.time.LocalDate的转化将
java.util.Date转换成java.time.LocalDate:java.util.Date date = new java.util.Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
将
java.time.LocalDate转换成java.util.Date:LocalDate localDate = LocalDate.now();
Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
java.util.Date date = java.util.Date.from(instant);