日期工具类DateTimeFormatter
简介
在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:
(1)非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,以及 SimpleDateFormat 的非线程安全,这是Java日期类最大的问题之一。
(2)设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
(3)时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
Java 8 在 java.time 包下提供了很多新的 API。
以下为两个比较重要的 API:
(1)Local(本地) − 简化了日期时间的处理,没有时区的问题。
(2)Zoned(时区) − 通过制定的时区处理日期时间。
新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。
关键类
Instant:瞬时实例。
LocalDate:本地日期,不包含具体时间 例如:2014-01-14 可以用来记录生日、纪念日、加盟日等。
LocalTime:本地时间,不包含日期。
LocalDateTime:组合了日期和时间,但不包含时差和时区信息。
ZonedDateTime:最完整的日期时间,包含时区和相对UTC或格林威治的时差。
新API还引入了 ZoneOffSet 和 ZoneId 类,使得解决时区问题更为简便。解析、格式化时间的 DateTimeFormatter
类也全部重新设计。
实际操作
package date;
import org.junit.Test;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
public class DateTest {
//1.获取今天的日期
@Test
public void getCurrentDate(){
// LocalDate 用于表示当天日期,它只有日期,不包含时间。
LocalDate today = LocalDate.now();
System.out.println("Today's Local date : " + today);
//这个是作为对比
Date date = new Date();
System.out.println(date);
}
//2.获取当前时间使用的是 LocalTime 类,默认的格式是hh:mm:ss:nnn。
@Test
public void getCurrentTime() {
LocalTime time = LocalTime.now();
System.out.println("local time now : " + time);
}
//3.增加小时,这些方法返回一个全新的LocalTime实例,由于其不可变性,返回后一定要用变量赋值。
@Test
public void plusHours() {
LocalTime time = LocalTime.now();
LocalTime newTime = time.plusHours(2); // 增加两小时
System.out.println("Time after 2 hours : " + newTime);
}
//4.如何计算一周后的日期,LocalDate日期不包含时间信息,
// 它的plus()方法用来增加天、周、月,ChronoUnit类声明了这些时间单位
@Test
public void nextWeek() {
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); //使用变量赋值
System.out.println("Today is : " + today);
System.out.println("Date after 1 week : " + nextWeek);
}
//5.计算一年前或一年后的日期,通过 minus() 方法计算一年前的日期
@Test
public void minusDate() {
LocalDate today = LocalDate.now();
LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
System.out.println("Date before 1 year : " + previousYear);
LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
System.out.println("Date after 1 year : " + nextYear);
}
//6.获取年、月、日信息
@Test
public void getDetailDate() {
LocalDate today = LocalDate.now();
System.out.println(today);
int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();
System.out.printf("Year : %d Month : %d day : %d t %n", year, month, day);
}
//7.处理特定日期
@Test
public void handleSpecilDate() {
//可以调用另一个有用的工厂方法 LocalDate.of() 创建任意日期,
// 该方法需要传入年、月、日做参数,返回对应的LocalDate实例
LocalDate dateOfBirth = LocalDate.of(2020, 06, 07);
System.out.println("The specil date is : " + dateOfBirth);
}
//8.判断两个日期是否相等
@Test
public void compareDate() {
//LocalDate 重载了equal方法。如果比较的日期是字符型的,需要先解析成日期对象再作判断。
LocalDate today = LocalDate.now();
LocalDate date1 = LocalDate.of(2020, 06, 07);
if (date1.equals(today)) {
System.out.printf("TODAY %s and DATE1 %s are same date %n", today, date1);
}
}
//9.处理周期性的日期,比如生日,法定假日
@Test
public void cycleDate() {
LocalDate today = LocalDate.now();
LocalDate dateOfBirth = LocalDate.of(2020, 06, 07);
//MonthDay这个类组合了月份和日,去掉了年,这意味着你可以用它判断每年都会发生事件。
MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
System.out.println("The birthday date is : " + birthday);
MonthDay currentMonthDay = MonthDay.from(today);
System.out.println("The currentMonthDay date is : " + currentMonthDay);
if (currentMonthDay.equals(birthday)) {
System.out.println("Many Many happy returns of the day !!");
} else {
System.out.println("Sorry, today is not your birthday");
}
}
//10.Clock 时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。
// 以前用到System.currentTimeInMillis() 和 TimeZone.getDefault() 的地方都可用Clock替换。
@Test
public void clock() {
// 根据系统时间返回当前时间并设置为UTC。
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock);
// 根据系统时钟区域返回时间
Clock defaultClock = Clock.systemDefaultZone();
System.out.println("Clock : " + clock);
}
//11.如何用Java判断日期是早于还是晚于另一个日期
@Test
public void isBeforeOrIsAfter() {
LocalDate today = LocalDate.now();
LocalDate tomorrow = LocalDate.of(2020, 6, 8);
if (tomorrow.isAfter(today)) {
System.out.println("Tomorrow comes after today");
}
//减去一天
LocalDate yesterday = today.minus(1, ChronoUnit.DAYS);
if (yesterday.isBefore(today)) {
System.out.println("Yesterday is day before today");
}
}
//12检查闰年
@Test
public void isLeapYear() {
LocalDate today = LocalDate.now();
if (today.isLeapYear()) {
System.out.println("This year is Leap year");
} else {
System.out.println("2020 is not a Leap year");
}
}
//13.计算两个日期之间的天数和月数
@Test
public void calcDateDays() {
LocalDate today = LocalDate.now();
LocalDate java8Release = LocalDate.of(2020, Month.DECEMBER, 23);
Period periodToNextJavaRelease = Period.between(today, java8Release);
//月份与月份比,天数与天数比
System.out.println("相差Months : "
+ periodToNextJavaRelease.getMonths()+"相差Days : "+ periodToNextJavaRelease.getDays());
}
//14.Instant类有一个静态工厂方法now()会返回当前的时间戳
@Test
public void getTimestamp() {
Instant timestamp = Instant.now();
System.out.println("What is value of this instant " + timestamp);
}
//15.使用预定义的格式化工具去解析或格式化日期
@Test
public void formateDate() {
//1.格式化成2020-06-07
String today = "20200607";
LocalDate fma1 = LocalDate.parse(today, DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("BASIC_ISO_DATE格式化后的时间:"+ fma1);
// 2.自定义格式化格式
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format1 = dtf.format(localDateTime);
System.out.println(format1);
//3.将字符串转化为日期
LocalDateTime parse = LocalDateTime.parse("2019-01-26T10:15:30");// 日期字符串转为日期
System.out.println(parse);
String format4 = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
System.out.println("1字符串转化为日期:"+format4);
//第一个参数时日期字符串,第二个参数是日期格式化的字符串类型
LocalDateTime parse2 = LocalDateTime.parse(format4,DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
System.out.println("1字符串转化为日期:"+parse2);
}
}