跳到主要内容

Java 日期

在 Java 编程语言中,日期类型是一种特殊的数据类型,用于存储日期和时间。Java 提供了多种日期类型,可以帮助我们处理日期和时间,并让我们能够实现日期和时间的计算。Java 中的日期类型可以分为两类:旧的日期类型和新的日期类型:

  • 旧的日期类型:包括 DateCalendar,它们可以用于表示日期和时间。Date 类是 Java 中最常用的日期类型,它可以让我们计算出任意日期之间的时间差。Calendar 类可以让我们计算出任意日期之间的天数或月数
  • 新的日期类型:Java 8 推出的新特性,称为新的日期和时间 API。它提供了一种更为简单的方式来处理日期和时间,允许开发人员更轻松地实现日期和时间的计算。新的日期和时间 API 包括 LocalDateLocalTimeLocalDateTime 等类,它们可以让我们处理日期和时间,而无需使用 DateCalendar

注:需导入 import java.util.Date;

Date 类相关

// 获取当前时间
Date date = new Date();
System.out.println(date);//输出的是当前时间
System.out.println(date.getTime());//输出的是当前时间戳
System.out.println(date.getDay());//输出的是当前属于星期几
System.out.println(date.getMonth());//输出的是当前是几月,注意jdk里面的月份是从0开始计算的
System.out.println(date.getYear());//输出的是当前的年,注意jdk里面的年是从1900年开始累积的,2023年输出的是123
System.out.println(date.getHours());//输出的是当前小时数
System.out.println(date.getMinutes());//输出的是当前分钟数
System.out.println(date.getSeconds());//输出的是当前秒数

// 获取指定时间
Calendar calendar = Calendar.getInstance();
calendar.set(2015, 11, 15);
Date date = calendar.getTime();

// 时间比较
Date date1 = new Date();
Date date2 = new Date();
if(date1.compareTo(date2) > 0) {
System.out.println("d1比d2晚");
} else if(date1.compareTo(date2) == 0) {
System.out.println("d1和d2相等");
} else {
System.out.println("d1比d2早");
}

// 时间转换
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = sdf.format(date);

// 时间添加
Date date = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH, 1); // 加一个月
date = calendar.getTime();

// 获取当前时区
TimeZone timeZone = TimeZone.getDefault();
System.out.println(timeZone.getDisplayName());

LocalDateTime 相关

// 比较两个日期的大小
LocalDateTime firstDateTime = LocalDateTime.of(2021, Month.JANUARY, 1, 10, 30);
LocalDateTime secondDateTime = LocalDateTime.of(2021, Month.JANUARY, 2, 10, 30);

if(firstDateTime.isBefore(secondDateTime)) {
System.out.println("firstDateTime is before secondDateTime");
}

// 使用LocalDateTime获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println("Current DateTime: " + now);

// 使用LocalDateTime获取指定日期时间
LocalDateTime specificDate = LocalDateTime.of(2021, Month.JANUARY, 1, 10, 30);
System.out.println("Specific DateTime: " + specificDate);

// 使用LocalDateTime对日期和时间进行加减
LocalDateTime dateTime = LocalDateTime.now();
System.out.println("Current DateTime: " + dateTime);

// 增加一天
LocalDateTime dateTimePlus = dateTime.plusDays(1);
System.out.println("Plus one day: " + dateTimePlus);

// 减少一个小时
LocalDateTime dateTimeMinus = dateTime.minusHours(1);
System.out.println("Minus one hour: " + dateTimeMinus);

总结

为什么 Java 8 的新日期/时间 API 比早期的 java.util 包更好?

  • 更加简便、可读性更好的 API,并且支持时区,更加安全可靠
  • 提供了用于计算、比较、格式化日期/时间的许多方法,以及用于将日期/时间转换为字符串的格式化方法,使得操作日期/时间变得更加容易

日期组件

Java 日期类主要有以下几个:

  • Date 类:转化后精度损失较多,不推荐使用
  • Calendar 类:比较繁琐,但提供了丰富的日期操作方法
  • SimpleDateFormat 类:可以将日期与字符串互相转化,常用于日期的格式化操作
  • LocalDate(日期)、LocalTime(时间)、LocalDateTime(日期和时间)、ZonedDateTime(带时区的日期和时间) 类:Java 8新增,使用简单,提供了丰富的日期操作方法,并且支持时区

Date 类

  • long getTime() 返回自1970年1月1日00:00:00 GMT以来此Date对象表示的毫秒数
  • void setTime(long time) 设置此Date对象表示时间点,以表示自1970年1月1日00:00:00 GMT以来的毫秒数。
  • boolean before(Date when) 当此Date对象表示的时间在when之前时,返回true,否则返回false
  • boolean after(Date when) 当此Date对象表示的时间在when之后时,返回true,否则返回false
  • boolean equals(Object obj) 当此Date对象表示的时间和obj表示的时间相同时,返回true,否则返回false

示例:

public class DateTest {
public static void main(String[] args) {
// 创建一个Date对象,表示当前时间
Date date = new Date();

// 使用getTime()方法获取当前时间的毫秒数
long time = date.getTime();

// 输出当前时间的毫秒数
System.out.println("当前时间的毫秒数为:" + time);

// 使用setTime()方法设置一个时间点,1970年1月1日08:00:00 GMT
date.setTime(28800000);

// 输出设置后的时间
System.out.println("设置后的时间为:" + date);

// 使用before()方法比较两个时间点
Date beforeDate = new Date(0);
boolean beforeResult = date.before(beforeDate);
System.out.println("设置的时间点在1970年1月1日之前:" + beforeResult);

// 使用after()方法比较两个时间点
Date afterDate = new Date(3600000);
boolean afterResult = date.after(afterDate);
System.out.println("设置的时间点在1970年1月1日之后:" + afterResult);

// 使用equals()方法比较两个时间点
boolean equalResult = date.equals(afterDate);
System.out.println("设置的时间点与当前时间相等:" + equalResult);
}
}

输出结果:

当前时间的毫秒数为:1718334238924
设置后的时间为:Thu Jan 01 16:00:00 CST 1970
设置的时间点在1970/1/1之前:false
设置的时间点在1970/1/1之后:true
设置的时间点与当前时间相等:false

Calendar 类

  • Calendar getInstance() 静态方法,用于获取由当前日期和时间初始化的Calendar对象。
  • void set(int field, int value) 将给定的时间字段(如年、月、日等)设置为给定值
  • void add(int field, int amount) 将给定的时间字段(如年、月、日等)的值按照给定的量进行加减运算
  • int get(int field) 获取指定时间字段的值
  • Date getTime() 返回以Date类型表示的Calendar对象当前表示的日期和时间
  • before(Object when)after(Object when) 用于比较所代表的日期是否在指定日期之前或之后(参数为Object类型,实际上通常传入的是Date类型对象)
  • 其它:getActualMaximum()getActualMinimum()、roll()

示例:

public class CalendarTest {
public static void main(String[] args) {
// 创建一个表示当前时间的Calendar对象
Calendar calendar = Calendar.getInstance();

// 输出年份、月份和日期
System.out.println("年份:" + calendar.get(Calendar.YEAR));
System.out.println("月份:" + (calendar.get(Calendar.MONTH) + 1));
System.out.println("日期:" + calendar.get(Calendar.DAY_OF_MONTH));

// 设置月份为10,日期为15
calendar.set(Calendar.MONTH, 9); // 月份从0开始计算,所以9表示10月
calendar.set(Calendar.DAY_OF_MONTH, 15);

// 输出修改后的日期
System.out.println("修改后的日期:" + calendar.getTime());

// 对日期进行加减
calendar.add(Calendar.DAY_OF_MONTH, 3); // 加3天
System.out.println("加3天后的日期:" + calendar.getTime());
calendar.add(Calendar.MONTH, -2); // 减2个月
System.out.println("减2个月后的日期:" + calendar.getTime());
}
}

SimpleDateFormat 类

  • SimpleDateFormat(String pattern) 构造一个新的SimpleDateFormat对象并使用指定的日期格式模式
  • String format(Date date) 将给定的日期对象格式化为字符串
  • Date parse(String source) 将给定的字符串解析为日期对象
  • void setLenient(boolean lenient) 指定解析日期时是否允许使用宽松的解析规则,默认为true,即启用宽松的解析规则

示例:

public class SimpleDateFormatTest {
public static void main(String[] args) throws Exception {
String dateString = "2021-01-31";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse(dateString);
System.out.println("Date object: " + date.toString());
String formattedDate = format.format(date);
System.out.println("Formatted date string: " + formattedDate);
}
}

LocalDate 类

  • now() 静态方法,用于获取当前系统日期
  • of(int year, int month, int dayOfMonth) 静态方法,用于创建指定日期的LocalDate对象
  • getYear()getMonthValue()getDayOfMonth() 获取日期的年、月、日
  • plusDays()plusMonths()plusYears() 将日期加上指定的天数、月数、年数
  • minusDays()minusMonths()minusYears() 将日期减去指定的天数、月数、年数
  • isBefore()isAfter() 用于比较当前日期是否在指定日期之前或之后
  • format() 将日期格式化为指定格式的字符串

示例:

public class LocalDateTest {
public static void main(String[] args) {
LocalDate now = LocalDate.now(); // 获取当前日期
String birthdayStr = "2000-05-20";
LocalDate birthday = LocalDate.parse(birthdayStr, DateTimeFormatter.ISO_LOCAL_DATE); // 解析生日字符串为LocalDate对象

Period period = Period.between(birthday, now); // 计算生日到当前日期相差的年、月、日
int years = period.getYears();
int months = period.getMonths();
int days = period.getDays();

System.out.printf("你已经活了 %d 年 %d 月 %d 天%n", years, months, days); // 输出相差的天数
}
}

使用技巧

在使用 Java 中的日期类时,有以下一些技巧可以提高开发效率和避免常见错误:

  • 使用 LocalDate 而不是 Date:Date 是 Java 早期版本中的日期类,不仅在处理时区和日期格式方面存在问题,而且通常需要使用 SimpleDateFormat 类进行日期格式化和解析。相反,Java 8 引入了新的日期和时间 API,其中包括 LocalDate 类。LocalDate 类提供了一种简单且线程安全的方式来表示日期,它还可以轻松进行格式化和解析,而不需要使用其他类
  • 使用预定义格式解析和格式化日期字符串:在使用 SimpleDateFormat 进行格式化和解析日期时,通常需要自己定义日期格式。这种方式容易出错且容易导致代码的可读性下降。Java 8中新增了 DateTimeFormatter 类,该类提供了预定义的日期格式以及自定义的格式化和解析。使用 DateTimeFormatter 类进行日期格式化和解析可以减少犯错的机会
  • 使用 Calendar 时要注意月份的索引从 0 开始:即 0 表示 1 月,1 表示 2 月,以此类推。这可能会导致混淆和错误,因此建议使用 LocalDate 代替
  • 使用 Period 和 Duration 进行日期和时间的计算:Period 和 Duration 类分别用于计算日期和时间之间的差异。这些类提供了易于使用且灵活的 API,可用于计算日期之间的差异(例如年、月和天)以及时间之间的差异(例如小时,分钟和秒)

总结:使用Java中的日期类时,建议使用新的日期和时间类 LocalDate,避免使用过时的 Date 和 Calendar 类