Java日期时间处理:从入门到精通
前言
在Java中,处理日期和时间是一项非常重要的技能,因为无论是记录日志、计算时间差,还是进行定时任务,都需要用到相关的API。本文会对一些常用的日期处理api进行介绍,并给出相关的使用示例。
一、Java 8之前的日期时间API
在Java 8之前,日期和时间的处理主要依赖于java.util.Date、java.util.Calendar和java.text.SimpleDateFormat等类。这些类虽然功能强大,但使用起来相对繁琐,且容易出错。
- java.util.Date:表示特定的瞬间,精确到毫秒。但它并不包含时区信息,且其很多方法都已经被废弃。
- java.util.Calendar:是一个抽象类,它为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下一个月的日期)提供了一些方法。但使用起来较为复杂。
- java.text.SimpleDateFormat:是一个日期时间格式化类,可以将Date对象格式化为字符串,也可以将字符串解析为Date对象。但线程不安全,且格式化模式字符串容易写错。
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class OldDateAPIExample {
public static void main(String[] args) {
// 创建一个Date对象
Date now = new Date();
System.out.println("当前时间(Date):" + now);
// 使用Calendar操作日期
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MONTH, 1); // 加一个月
Date nextMonth = calendar.getTime();
System.out.println("下一个月的时间(Calendar):" + nextMonth);
// 格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = sdf.format(now);
System.out.println("格式化后的时间:" + formattedDate);
}
}
二、Java 8引入的新日期时间API
Java 8引入了全新的日期时间API,位于java.time包下,这些API设计得更合理、易用,且线程安全。主要包括LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Instant、Duration等类。
- LocalDate:表示不带时间的日期,例如:2023-03-15。
- LocalTime:表示不带日期的时间,例如:14:30:45。
- LocalDateTime:表示日期和时间,例如:2023-03-15T14:30:45。
- ZonedDateTime:表示带时区信息的日期时间。
- Instant:表示从1970-01-01T00:00:00Z开始的一个时间点。
- Duration:表示两个时间点之间的持续时间。
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.Instant;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
public class NewDateAPIExample {
public static void main(String[] args) {
// 创建LocalDate、LocalTime、LocalDateTime对象
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("今天的日期:" + today);
System.out.println("当前的时间:" + now);
System.out.println("当前的日期时间:" + nowDateTime);
// 使用ZonedDateTime处理时区
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println("带时区的当前日期时间:" + zonedDateTime);
// 使用Instant处理时间点
Instant instant = Instant.now();
System.out.println("当前的时间点(Instant):" + instant);
// 计算两个时间点之间的Duration
Instant startTime = Instant.now();
// 模拟耗时操作...
Instant endTime = Instant.now();
Duration duration = Duration.between(startTime, endTime);
System.out.println("耗时:" + duration.toMillis() +
三、使用Java8引进的新日期时间api造一个日期处理的工具类轮子
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.format.DateTimeFormatter;
import java.time.Duration;
import java.time.Period;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Locale;
/**
* @Author Jzs
* @Date 2024/3/14
*/
public class DateUtil {
// 默认的日期时间格式
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
private static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT);
// 获取当前日期
public static LocalDate getCurrentDate() {
return LocalDate.now();
}
// 获取当前时间(不包含日期)
public static LocalTime getCurrentTime() {
return LocalTime.now();
}
// 获取当前日期时间
public static LocalDateTime getCurrentDateTime() {
return LocalDateTime.now();
}
// 获取带时区的当前日期时间
public static ZonedDateTime getCurrentZonedDateTime() {
return ZonedDateTime.now();
}
// 格式化日期时间
public static String formatDateTime(LocalDateTime dateTime, String pattern) {
return dateTime.format(DateTimeFormatter.ofPattern(pattern));
}
// 格式化日期
public static String formatDate(LocalDate date, String pattern) {
return date.format(DateTimeFormatter.ofPattern(pattern));
}
// 格式化时间
public static String formatTime(LocalTime time, String pattern) {
return time.format(DateTimeFormatter.ofPattern(pattern));
}
// 使用默认格式格式化日期时间
public static String formatDateTime(LocalDateTime dateTime) {
return formatDateTime(dateTime, DEFAULT_DATE_TIME_FORMAT);
}
// 使用默认格式格式化日期
public static String formatDate(LocalDate date) {
return formatDate(date, "yyyy-MM-dd");
}
// 解析日期时间字符串
public static LocalDateTime parseDateTime(String dateTimeStr, String pattern) {
return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern));
}
// 解析日期字符串
public static LocalDate parseDate(String dateStr, String pattern, Locale aDefault) {
return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
}
// 解析时间字符串
public static LocalTime parseTime(String timeStr, String pattern) {
return LocalTime.parse(timeStr, DateTimeFormatter.ofPattern(pattern));
}
// 计算两个日期之间的天数差
public static long daysBetween(LocalDate date1, LocalDate date2) {
return ChronoUnit.DAYS.between(date1, date2);
}
// 计算两个日期时间之间的时长差(以秒为单位)
public static long durationInSecondsBetween(LocalDateTime dateTime1, LocalDateTime dateTime2) {
return Duration.between(dateTime1, dateTime2).getSeconds();
}
// 计算两个日期之间的年、月、日差
public static Period periodBetween(LocalDate date1, LocalDate date2) {
return Period.between(date1, date2);
}
// 将java.util.Date转换为java.time.LocalDateTime
public static LocalDateTime convertDateToLocalDateTime(Date date) {
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
// 将java.time.LocalDateTime转换为java.util.Date
public static Date convertLocalDateTimeToDate(LocalDateTime dateTime) {
return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
}
// 根据不同的语言环境格式化日期时间
public static String formatDateTimeWithLocale(LocalDateTime dateTime, String pattern, Locale locale) {
return dateTime.format(DateTimeFormatter.ofPattern(pattern).withLocale(locale));
}
// 获取一年中的第几周
public static int getWeekOfYear(LocalDate date) {
return date.get(ChronoField.ALIGNED_WEEK_OF_YEAR);
}
// 计算两个日期之间的月份差
public static long monthsBetween(LocalDate date1, LocalDate date2) {
return ChronoUnit.MONTHS.between(date1, date2);
}
// 判断日期是否在某个范围内(包含边界)
public static boolean isDateBetween(LocalDate date, LocalDate startDate, LocalDate endDate) {
return !date.isBefore(startDate) && !date.isAfter(endDate);
}
// 获取日期所在月份的第一天
public static LocalDate getFirstDayOfMonth(LocalDate date) {
return date.with(TemporalAdjusters.firstDayOfMonth());
}
// 获取日期所在月份的最后一天
public static LocalDate getLastDayOfMonth(LocalDate date) {
return date.with(TemporalAdjusters.lastDayOfMonth());
}
// 其他需要的方法可以在这里继续添加...
public static void main(String[] args) {
LocalDate date = LocalDate.now();
// 测试格式化日期
String formattedDate = formatDate(date, "yyyy-MM-dd");
System.out.println("Formatted date time: " + formattedDate);
// 测试解析日期字符串
String dateString = formattedDate;
LocalDate parsedDate = parseDate(dateString, "yyyy-MM-dd", Locale.getDefault());
System.out.println("Parsed date: " + parsedDate);
// 测试获取一年中的第几周
System.out.println(getWeekOfYear(date));
// 测试计算月份差
System.out.println(monthsBetween(LocalDate.of(2020, 1, 1), LocalDate.of(2020, 3, 1)));
// 测试判断日期是否在范围内
System.out.println(isDateBetween(LocalDate.of(2023, 1, 15), LocalDate.of(2023, 1, 1), LocalDate.of(2023, 1, 31)));
// 测试获取月份的第一天和最后一天
System.out.println("First day of month: " + getFirstDayOfMonth(date));
System.out.println("Last day of month: " + getLastDayOfMonth(date));
}
}