JDK与时间相关的包和API: # 包 包 | 引入 | 描述 -------|------|------------- java.time | 1.8+ | 推荐使用 java.util | 旧版 | 不推荐 java.text | 旧版 | 日期字符串格式化相关,不推荐使用 java.sql | 1.1 | 数据库相关,业务不推荐使用 java.time.chrono| 1.8 | 可选,能不用就不用。支持非 ISO 历法系统 # java.time包中的类 | 类/接口 | 用途 | | ------------------- | --------------------- | | `LocalDate` | 日期(年-月-日) | | `LocalTime` | 时间(时:分:秒.纳秒) | | `LocalDateTime` | 日期+时间 | | `ZonedDateTime` | 带时区的日期时间 | | `Instant` | 时间戳(从1970-01-01的秒/毫秒) | | `Duration` | 时间间隔(基于秒和纳秒) | | `Period` | 日期间隔(基于年月日) | | `DateTimeFormatter` | 日期时间格式化 | LocalDate,LocalTime,LocalDateTime都是指表示一个时间数字,没有时区概念。比如LocalTime表示8:20,并不能表示出具体的时间,需要结合时区才能知道是哪里的8:20。 java.time.format DateTimeFormatter 及其相关类 用于格式化与解析日期时间 java.time.temporal 时间访问和调整的底层接口 包含 Temporal, TemporalField, TemporalUnit 等 java.time.zone 时区相关类 ZoneId, ZoneOffset, ZoneRules 等 # java.util包中的类 | 类 | 说明 | | ---------- |-------------------| | `Date` | 传统日期类(已不推荐),不带时区 | | `Calendar` | 日历计算(已不推荐),默认系统时区 | | `TimeZone` | 时区信息 | # java.text包中的类 SimpleDateFormat - 旧版日期格式化(线程不安全) # java.sql 这些也都没有时区概念,只表示时间值 | 类 | 用途 | | ----------- | ------- | | `Date` | SQL 日期 | | `Time` | SQL 时间 | | `Timestamp` | SQL 时间戳 | # 最佳实践 关于时区: 1. 系统内部应该只用java.time下的LocalDate,LocalTime,LocalDateTime这些不带时区的概念。 2. 只有与外部交互时,才应该转成带时区的概念。 比如把前端请求的日期转成LocalDateTime,返回给前端的时间应该转成前端对应时区的时间。或者请求外部依赖时,需要传递时间,应该确定好时区的概念。 3. 定时任务的时间设置应该带上时区,否则将会按照系统所在时区执行,切换服务器时,时区会变,定时任务的执行时间也会变。 作为中国开发者,应该都用东八区时间。`@Scheduled(cron = "2 15 0 * * ?", zone = "Asia/Shanghai")` 4. 服务器的时区都设置成东八区时间 查看时区:`timedatectl` 列出可支持的时区:`timedatectl list-timezones | grep Shanghai` 设置时区:`sudo timedatectl set-timezone Asia/Shanghai` 关于存储时间的格式: 1. 系统中只允许使用LocalDateTime,或者Long时间戳存储时间。优先用LocalDateTime,既拥有时间戳的所有信息,也有丰富的API操作时间。