java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java时间操作类

Java 中的所有时间操作类详解及使用实战

作者:猩火燎猿

Java时间处理API演进与应用指南,本文系统介绍了Java中时间处理API的发展历程和实用技巧,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

一、早期时间类

1.java.util.Date

Date date = new Date();
System.out.println(date); // 当前时间

2.java.util.Calendar

Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, 5); // 当前日期加5天
Date newDate = cal.getTime();

3.java.text.SimpleDateFormat

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = sdf.format(new Date());
Date date = sdf.parse("2024-06-01 12:00:00");

二、Java 8 引入的现代时间API(推荐)

所有类都在 java.time 包下,线程安全,易于使用。

1.LocalDate

LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);

2.LocalTime

LocalTime time = LocalTime.now();
LocalTime later = time.plusHours(2);

3.LocalDateTime

LocalDateTime ldt = LocalDateTime.now();
LocalDateTime future = ldt.plusDays(3).plusHours(5);

4.ZonedDateTime

ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

5.Instant

Instant instant = Instant.now();
long epochMilli = instant.toEpochMilli();

6.Duration&Period

Duration duration = Duration.between(LocalTime.now(), LocalTime.now().plusHours(2));
Period period = Period.between(LocalDate.now(), LocalDate.now().plusDays(10));

7.DateTimeFormatter

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = formatter.format(LocalDateTime.now());
LocalDateTime ldt = LocalDateTime.parse("2024-06-01 12:00:00", formatter);

8.ZoneId&ZoneOffset

ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZoneOffset offset = ZoneOffset.of("+08:00");

三、其他相关类

1.java.sql.Date、java.sql.Time、java.sql.Timestamp

四、时间类关系图

java.util.Date
    ├─ java.sql.Date
    ├─ java.sql.Time
    └─ java.sql.Timestamp
java.util.Calendar
    └─ java.util.GregorianCalendar
java.text.SimpleDateFormat
java.time.LocalDate
java.time.LocalTime
java.time.LocalDateTime
java.time.ZonedDateTime
java.time.Instant
java.time.Duration
java.time.Period
java.time.DateTimeFormatter
java.time.ZoneId
java.time.ZoneOffset

五、常用时间操作示例​​​​​​

// 当前日期时间
LocalDateTime now = LocalDateTime.now();
// 日期加减
LocalDateTime tomorrow = now.plusDays(1);
LocalDateTime lastWeek = now.minusWeeks(1);
// 日期格式化
String str = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 字符串转日期
LocalDateTime ldt = LocalDateTime.parse("2024-06-01 12:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 时间差
Duration duration = Duration.between(now, tomorrow);
long hours = duration.toHours();

六、建议

七. 各时间类详细用法与实战场景

1.1 LocalDate

场景:只关心日期(如生日、节假日、账单日期)

​​​​​​​​​​​​

LocalDate birthday = LocalDate.of(1995, 6, 1);
LocalDate today = LocalDate.now();
// 判断是否是今天
boolean isToday = birthday.equals(today);
// 获取本月第一天
LocalDate firstDay = today.withDayOfMonth(1);
// 获取本月最后一天
LocalDate lastDay = today.withDayOfMonth(today.lengthOfMonth());
// 日期加减
LocalDate nextWeek = today.plusWeeks(1);
LocalDate lastYear = today.minusYears(1);

1.2 LocalTime

场景:只关心时间(如打卡时间、会议时间)

LocalTime startTime = LocalTime.of(9, 0, 0);
LocalTime endTime = LocalTime.of(18, 0, 0);
// 判断是否在工作时间内
LocalTime now = LocalTime.now();
boolean isWorkTime = !now.isBefore(startTime) && !now.isAfter(endTime);
// 时间加减
LocalTime lunchTime = startTime.plusHours(4);

1.3 LocalDateTime

场景:关心日期和时间(如订单创建时间、日志时间)

LocalDateTime orderTime = LocalDateTime.now();
LocalDateTime expireTime = orderTime.plusHours(2);
// 比较先后
boolean isExpired = LocalDateTime.now().isAfter(expireTime);
// 获取年月日时分秒
int year = orderTime.getYear();
int month = orderTime.getMonthValue();
int day = orderTime.getDayOfMonth();
int hour = orderTime.getHour();
int minute = orderTime.getMinute();

1.4 ZonedDateTime

场景:全球化应用,关心时区(如国际会议、航班时间)

ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYorkTime = shanghaiTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// 获取时区
ZoneId zoneId = shanghaiTime.getZone();

1.5 Instant

场景:存储时间戳(如数据库、消息队列)、高精度时间计算

Instant now = Instant.now();
long timestamp = now.toEpochMilli(); // 毫秒时间戳
// Instant与LocalDateTime互转
LocalDateTime ldt = LocalDateTime.ofInstant(now, ZoneId.systemDefault());
Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();

1.6 Duration & Period

场景:计算时间差

// Duration: 时间点之间的差(如秒、纳秒)
Duration duration = Duration.between(ldt1, ldt2);
long seconds = duration.getSeconds();
long minutes = duration.toMinutes();
// Period: 日期之间的差(如年、月、日)
Period period = Period.between(date1, date2);
int days = period.getDays();
int months = period.getMonths();
int years = period.getYears();

2. 时间比较与排序

LocalDateTime t1 = LocalDateTime.of(2024, 6, 1, 12, 0);
LocalDateTime t2 = LocalDateTime.of(2024, 6, 2, 12, 0);
boolean isBefore = t1.isBefore(t2); // true
boolean isAfter = t1.isAfter(t2);   // false
boolean isEqual = t1.isEqual(t2);   // false
// 排序
List<LocalDateTime> list = Arrays.asList(t1, t2);
list.sort(Comparator.naturalOrder());

3. 与旧API兼容与转换

Date <-> LocalDateTime

// Date转LocalDateTime
Date date = new Date();
Instant instant = date.toInstant();
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// LocalDateTime转Date
LocalDateTime ldt2 = LocalDateTime.now();
Instant instant2 = ldt2.atZone(ZoneId.systemDefault()).toInstant();
Date date2 = Date.from(instant2);

4. 时间格式化与解析(自定义格式)

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
// 格式化
String str = LocalDateTime.now().format(fmt);
// 解析
LocalDateTime ldt = LocalDateTime.parse("2024/06/01 13:45:30", fmt);

5. 时区处理

// 获取所有可用时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
// 当前时间在不同地区
ZonedDateTime utcTime = ZonedDateTime.now(ZoneId.of("UTC"));
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

6. 常见坑与注意事项

  1. 月份从1开始(不是0)
  2. LocalDateTime没有时区信息,存储时要注意转换
  3. SimpleDateFormat线程不安全,推荐用DateTimeFormatter
  4. Duration不能用于日期(用Period
  5. DateCalendar已过时,避免新项目使用
  6. 时间操作建议统一使用一种API,避免混用造成混乱

7. 进阶用法

7.1 时间区间判断

LocalDateTime now = LocalDateTime.now();
LocalDateTime start = LocalDateTime.of(2024, 6, 1, 9, 0);
LocalDateTime end = LocalDateTime.of(2024, 6, 1, 18, 0);
boolean inRange = !now.isBefore(start) && !now.isAfter(end);

7.2 按天、月、年循环

// 按天循环
LocalDate start = LocalDate.of(2024, 6, 1);
LocalDate end = LocalDate.of(2024, 6, 10);
for (LocalDate d = start; !d.isAfter(end); d = d.plusDays(1)) {
    System.out.println(d);
}

7.3 时间差友好显示

Duration duration = Duration.between(ldt1, ldt2);
long hours = duration.toHours();
long minutes = duration.toMinutes() % 60;
System.out.println(hours + "小时" + minutes + "分钟");

8. 代码片段汇总

// 获取当前时间戳(秒/毫秒)
long epochSecond = Instant.now().getEpochSecond();
long epochMilli = Instant.now().toEpochMilli();
// 时间加减
LocalDateTime t = LocalDateTime.now().plusDays(3).minusHours(2);
// 时间格式化
String s = t.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 时间解析
LocalDateTime parsed = LocalDateTime.parse("2024-06-01 12:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
// 时间区间
LocalDate start = LocalDate.of(2024, 6, 1);
LocalDate end = LocalDate.of(2024, 6, 10);
for (LocalDate d = start; !d.isAfter(end); d = d.plusDays(1)) {
    // ...
}

9. 时间操作常见应用场景实战

9.1 时间区间的交集与重叠判断

在预订系统、排班系统等场景,经常需要判断两个时间段是否有重叠。

public static boolean isOverlap(LocalDateTime start1, LocalDateTime end1,
                                LocalDateTime start2, LocalDateTime end2) {
    return !start1.isAfter(end2) && !start2.isAfter(end1);
}
// 示例
LocalDateTime s1 = LocalDateTime.of(2024, 6, 1, 10, 0);
LocalDateTime e1 = LocalDateTime.of(2024, 6, 1, 12, 0);
LocalDateTime s2 = LocalDateTime.of(2024, 6, 1, 11, 0);
LocalDateTime e2 = LocalDateTime.of(2024, 6, 1, 13, 0);
boolean overlap = isOverlap(s1, e1, s2, e2); // true

9.2 日期的周期性操作(如每周一的定时任务)

// 获取本周的所有日期
LocalDate monday = LocalDate.now().with(DayOfWeek.MONDAY);
for (int i = 0; i < 7; i++) {
    LocalDate d = monday.plusDays(i);
    System.out.println(d + " " + d.getDayOfWeek());
}

9.3 计算某月的第一天和最后一天

LocalDate now = LocalDate.now();
LocalDate firstDay = now.withDayOfMonth(1);
LocalDate lastDay = now.withDayOfMonth(now.lengthOfMonth());

9.4 获取某天的开始和结束时间

LocalDate date = LocalDate.of(2024, 6, 1);
LocalDateTime startOfDay = date.atStartOfDay();
LocalDateTime endOfDay = date.atTime(LocalTime.MAX); // 23:59:59.999999999

9.5 时间格式化为友好字符串(如“刚刚”、“1分钟前”、“1天前”)

public static String friendlyTime(LocalDateTime time) {
    Duration duration = Duration.between(time, LocalDateTime.now());
    long seconds = duration.getSeconds();
    if (seconds < 60) return "刚刚";
    if (seconds < 3600) return (seconds / 60) + "分钟前";
    if (seconds < 86400) return (seconds / 3600) + "小时前";
    return (seconds / 86400) + "天前";
}

9.6 日期时间的序列化与反序列化(如 JSON)

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;

10. 时间操作的性能与线程安全

新 API(java.time)都是不可变对象,线程安全。
旧 API(Date、Calendar、SimpleDateFormat)都非线程安全。

示例:多线程格式化日期时,推荐如下写法:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Runnable task = () -> {
    String formatted = LocalDateTime.now().format(formatter);
    System.out.println(formatted);
};
new Thread(task).start();

11. 时间的国际化与本地化

11.1 不同区域的日期格式

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日", Locale.CHINA);
String str = LocalDate.now().format(formatter); // 2024年06月01日

11.2 不同国家的周起始日

LocalDate date = LocalDate.now();
DayOfWeek firstDayOfWeek = WeekFields.of(Locale.US).getFirstDayOfWeek(); // SUNDAY
DayOfWeek firstDayOfWeekCN = WeekFields.of(Locale.CHINA).getFirstDayOfWeek(); // MONDAY

12. 时间工具类封装示例

你可以将常用操作封装为工具类,便于项目复用:

public class DateTimeUtils {
    public static String format(LocalDateTime time, String pattern) {
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }
    public static LocalDateTime parse(String str, String pattern) {
        return LocalDateTime.parse(str, DateTimeFormatter.ofPattern(pattern));
    }
    public static long diffMinutes(LocalDateTime start, LocalDateTime end) {
        return Duration.between(start, end).toMinutes();
    }
    // 更多方法...
}

13. 时间操作常见面试题

  1. 如何获取某个月的最后一天?
  2. 如何判断两个时间段是否有重叠?
  3. 如何将 Date 转换为 LocalDateTime?
  4. 如何计算两个日期之间的天数?
  5. 如何格式化为“刚刚”、“几分钟前”?

14. 未来趋势和常用第三方库

15. 其他常见问题与补充

到此这篇关于Java 中的所有时间操作类详解及使用实战的文章就介绍到这了,更多相关java时间操作类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文