当前位置: 首页 > news >正文

Java8:新日期时间

目录

1、旧API问题

2、核心设计理念

3、核心类和使用方法

3.1 不含时区的日期/时间

3.2 带时区的日期/时间

3.3 时间点和时间间隔

3.4 格式化与解析

4、使用技巧

5、案例


1、旧API问题

在 Java 8 之前,主要使用 java.util.Date 和 java.util.Calendar 来处理日期和时间。这些旧的 API 存在诸多问题:

  • 设计缺陷Date 类既包含日期,又包含时间,但它的名字却只体现了“日期”。Calendar 的设计也非常繁琐和反直觉。

  • 可变性Date 和 Calendar 对象都是可变的,这意味着它们不是线程安全的。在多线程环境下需要额外小心。

  • 时区处理困难:时区逻辑分散在 DateCalendar 和 TimeZone 类中,使用起来非常混乱和容易出错。

  • API 难用:简单的日期计算(如加一周、减一天)都需要通过 Calendar 进行复杂操作,代码冗长且不易读。

  • 格式化问题SimpleDateFormat 也是非线程安全的,同样需要小心使用。

为了解决这些问题,Java 8 借鉴了非常成功的 Joda-Time 库,并由其核心贡献者 Stephen Colebourne 主导,创建了全新的 java.time API。

2、核心设计理念

  • 不可变:所有核心类都是不可变的。任何修改操作都会返回一个新的对象。这保证了线程安全,无需额外的同步。

  • 清晰的分工:将日期、时间、日期时间、时区、时刻等概念用不同的类清晰地表示。

  • 流式 API:方法调用可以像链条一样连接,使代码更流畅、更易读。

  • 基于 ISO-8601 标准:默认遵循国际标准日历系统。

  • 可扩展性:支持不同的日历系统(如日本历、泰国佛历等)。

3、核心类和使用方法

3.1 不含时区的日期/时间

描述示例 (格式:ISO-8601)
LocalDate只表示日期,不包含时间和时区。2023-10-27
LocalTime只表示时间,不包含日期和时区。15:30:00.123
LocalDateTime表示日期和时间的组合,但不带时区信息。2023-10-27T15:30:00.123
// 获取当前日期时间
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime currentDateTime = LocalDateTime.now();// 指定日期时间创建对象
LocalDate birthday = LocalDate.of(1990, Month.AUGUST, 15);
LocalTime meetingTime = LocalTime.of(14, 30); // 14:30
LocalDateTime projectDeadline = LocalDateTime.of(2023, 12, 31, 23, 59, 59);// 从字符串解析 (必须严格遵守ISO格式)
LocalDate date = LocalDate.parse("2023-10-27");
LocalDateTime dateTime = LocalDateTime.parse("2023-10-27T15:30:00");// 获取特定字段的值
int year = today.getYear();
Month month = today.getMonth(); // 返回 Month 枚举
int dayOfMonth = today.getDayOfMonth();
int hour = now.getHour();// 日期时间的加减 (返回新对象,原对象不变)
LocalDate nextWeek = today.plusWeeks(1);
LocalDate previousMonth = date.minusMonths(1);
LocalDateTime yesterdaySameTime = currentDateTime.minusDays(1);
LocalTime inAnHour = now.plusHours(1).plusMinutes(10);// 比较
boolean isAfter = birthday.isAfter(today);
boolean isBefore = meetingTime.isBefore(now);// 调整器(TemporalAdjuster)
LocalDate firstDayOfMonth = date.with(TemporalAdjusters.firstDayOfMonth());
LocalDate nextMonday = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));// 自定义调整
LocalDate nextWorkingDay = date.with(temporal -> {DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));int daysToAdd = 1;if (dow == DayOfWeek.FRIDAY) daysToAdd = 3;if (dow == DayOfWeek.SATURDAY) daysToAdd = 2;return temporal.plus(daysToAdd, ChronoUnit.DAYS);
});

3.2 带时区的日期/时间

描述
ZonedDateTime一个带有时区的完整的日期和时间。它可以对应到时间线上的一个确定的时刻。
OffsetDateTime一个带有与 UTC 偏移量的日期和时间,但不包含时区规则(如夏令时)。

ZonedDateTime 示例:

// 获取系统默认时区的当前时间
ZonedDateTime zonedNow = ZonedDateTime.now();// 时区ID
Set<String> availableZones = ZoneId.getAvailableZoneIds();// 获取指定时区的当前时间
ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
ZonedDateTime tokyoTime = ZonedDateTime.now(tokyoZone);// 从 LocalDateTime 添加时区
LocalDateTime localDateTime = LocalDateTime.of(2023, 10, 27, 15, 30);
ZonedDateTime beijingTime = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));// 时区转换
ZonedDateTime newYorkTime = beijingTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// 此时 newYorkTime 的时间会比 beijingTime 晚 12 小时(夏令时期间)System.out.println(beijingTime); // 2023-10-27T15:30+08:00[Asia/Shanghai]
System.out.println(newYorkTime); // 2023-10-27T03:30-04:00[America/New_York]// 偏移量时间
OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneOffset.of("+08:00"));

3.3 时间点和时间间隔

描述
Instant时间线上的一个瞬时点(时间戳)。通常用于机器时间,表示自 1970-01-01T00:00:00Z (UTC) 开始的秒和纳秒。
Duration表示一个以秒和纳秒为单位的时间量。用于测量基于时间的间隔(如“2小时30分钟”)。
Period表示一个以年、月、日为单位的日期量。用于测量基于日期的间隔(如“3年2个月1天”)。
// Instant - 机器时间
Instant instant = Instant.now(); // 获取当前UTC时刻
Instant fromEpochMilli = Instant.ofEpochMilli(System.currentTimeMillis());
Instant later = instant.plusSeconds(3600);// Duration - 时间间隔
LocalTime start = LocalTime.of(9, 0);
LocalTime end = LocalTime.of(17, 30);
Duration duration = Duration.between(start, end);
System.out.println(duration.toHours()); // 8
System.out.println(duration.toMinutes()); // 510// 也可以直接创建
Duration twoHours = Duration.ofHours(2);// Period - 日期段
LocalDate startDate = LocalDate.of(2020, 1, 1);
LocalDate endDate = LocalDate.of(2023, 10, 27);
Period period = Period.between(startDate, endDate);
System.out.println(period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "天");
// 输出:3年9月26天// 也可以直接创建
Period oneWeek = Period.ofWeeks(1);

3.4 格式化与解析

DateTimeFormatter 类替代了旧的 SimpleDateFormat,并且是线程安全的。

// 使用预定义的格式化器
LocalDateTime now = LocalDateTime.now();
String isoFormat = now.format(DateTimeFormatter.ISO_DATE_TIME);
String basicIsoDate = now.format(DateTimeFormatter.BASIC_ISO_DATE);// 使用自定义模式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");
String customFormat = now.format(formatter); // 输出:2023年10月27日 15:30:00 周五// 从字符串解析回对象
LocalDateTime parsedDateTime = LocalDateTime.parse("2023/10/27 15:30", DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));


4、使用技巧

  • 何时使用哪个类?

    • 如果只需要日期,用 LocalDate

    • 如果只需要时间,用 LocalTime

    • 如果需要日期和时间,但不涉及时区,用 LocalDateTime(例如,会议时间、生日)。

    • 如果需要明确表示一个时间点(比如在数据库中存储时间戳),或者需要跨时区计算,用 Instant 或 ZonedDateTime

    • 如果需要和数据库交互,大多数 JDBC 驱动都支持 java.time 类型(LocalDateLocalTimeLocalDateTime)。

  • 与旧 API 的转换

    • 新的 API 提供了 from()to() 等方法与旧的 Date 和 Calendar 进行互转。

    • 例如,Date.from(instant) 和 Date.toInstant()

  • 时区处理

    • 始终使用 ZoneId 的 region ID(如 "Asia/Shanghai"),而不是固定的偏移量(如 "+08:00"),因为 region ID 会自动处理夏令时等规则。

5、案例

public class DateUtils {// 计算年龄public static int calculateAge(LocalDate birthDate) {return Period.between(birthDate, LocalDate.now()).getYears();}// 检查是否在工作时间public static boolean isWorkingHours(LocalDateTime dateTime) {LocalTime time = dateTime.toLocalTime();DayOfWeek day = dateTime.getDayOfWeek();return !day.equals(DayOfWeek.SATURDAY) && !day.equals(DayOfWeek.SUNDAY)&& time.isAfter(LocalTime.of(9, 0))&& time.isBefore(LocalTime.of(18, 0));}// 获取下个工作日public static LocalDate getNextWorkingDay(LocalDate date) {return date.with(temporal -> {// 获取星期几DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));// 默认下个工作日是明天int daysToAdd = 1;if (dow == DayOfWeek.FRIDAY) daysToAdd = 3;else if (dow == DayOfWeek.SATURDAY) daysToAdd = 2;return temporal.plus(daysToAdd, ChronoUnit.DAYS);});}
}

http://www.dtcms.com/a/541805.html

相关文章:

  • Java_String对象特性
  • 网站做app的软件有哪些360安全浏览器
  • 网站建设 互成网络amp 网站开发
  • 网站app免费生成软件下载免费 片
  • USB基础知识--Endpoint与pipe
  • SpringBoot拦截器实战与原理剖析
  • 把握智能语音风口:云蝠智能【声・纪元】VoiceAgent 实时语音智能论坛邀您同行
  • 一文吃透二叉树、完全平衡树、红黑树原理及C语言实现
  • 做网站用别人的图片沈阳设计公司排名
  • 浙江自己如何做网站wordpress 做后台
  • 网站 模板下载陕西富通建设有限公司网站
  • 淄博高效网站建设免费网站建站模板
  • Bootstrap4 Jumbotron详解与使用指南
  • IoT技术在产线实践中的应用
  • 合格VR大空间企业:核心要素有哪些?
  • 06.OpenStack网络管理
  • C++学习记录(23)智能指针
  • 网站内容策划方案wordpress底部版权信息修改
  • python 在class中几种函数的定义和用法
  • 电商数据中台基石:通过 API 构建淘宝商品实时数据源
  • 川崎机器人焊接电源气体省气
  • 理想汽车基于 Hologres + Flink 构建万亿级车联网信号实时分析平台
  • php教育视频网站开发如何做古诗词网站
  • 自发购卡网站在吗做手机建立网站软件
  • Git Tag 理解和使用
  • 如何写一个WebRTC ACE音频应用处理模块
  • 当机器拥有感觉:从电子皮肤到视频神经系统的具身智能革命
  • 快速搭建网站服务器网站推广策划方案
  • 【Linux基础知识系列:第一百六十三篇】创建虚拟网络:Linux网络桥接
  • 东方财经报道|深兰科技落户张江,AI医疗与情感陪伴并进,拓展智能未来版图