处理日期和时间
概念
日期、时间和时刻
时区TimeZone:
GMT+08:00
UTC+08:00
CST:China Standard Time / Central Standard Time USA
Asia/Shanghai
夏令时,同一地区用GMT/UTC和城市表示的时区可能导致时间不同
Locale用来针对当地用户习惯格式化日期、时间、数字、货币等
Date和Calendar
Date
Epoch Time:从1970-01-01 00:00:00 GMT+0:00开始到现在的秒数
JDK有新旧两套API处理日期和时间
java.util | java.time(JDK >= 1.8) |
---|---|
Date、Calendar | LocalDate、LocalTime、ZonedDateTime、Instant |
java.util.Date表示日期和时间,内部使用long表示epoch毫秒数
java.util.Date转化为String:
1)toString()
2)toGMTString()
3)toLocaleString()
4)SimpleDateFormat()
SimpleDateFormat:用于Date和String的解析和格式化
Calendar
Calendar和Date、long可以互相转换
Calendar可以用set、get设置和获取指定字段
Calendar可以实现
1)设置特定的日期和时间
2)设置时区并获得转换后的时间
3)加减日期和时间
TimeZone表示时区,getAvailableIDs()可以枚举所有有效的时区ID
java.time的API
LocalDateTime
java.time提供了新的API
1)LocalDate
2)LocalTime
3)LocalDateTime
4)ZonedDateTime
5)ZoneId
6)Instant
7)Formatter
新API特点
1)严格区分日期和时间
2)不变类
3)修复了Month和Week的常量值
Month范围1~12(Jan~Dec)
Week范围1~7(Mon~Sun)
LocalDate:日期
LocalTime:时间
LocalDateTime:日期+时间
DateTimeFormatter:格式化日期和时间
默认按ISO 8601解析和格式化
可以对日期和时间进行加减、调整、判断先后,计算Period
对日期进行加减
// 加减
plusDays()
minusHours()
plusWeeks()
...
// 调整
withDayOfMonth()
withMonth()
withHour()
...
with()
// 判断时间先后
isBefore()
isAfter()
equals()
// 计算日期的Period
getYears()
getMonths()
getDays()
LocalDateTime没有时区信息,无法与long进行转换
ZonedDateTime
ZonedDateTime = LocalDateTime + ZoneId
ZonedDateTime可以做时区转换:withZoneSameInstant
ZoneId:新的时区对象
Instant:时刻,可以转换为long(单位秒)
ZonedDateTime、Instant和long可以互相转换
ZonedDateTime.toInstant()
Instant.getEpochSecond()
Period和Duration表示一段时间,可以用于日期和时间加减
其他底层API:
ZoneOffset:时区偏移量
OffsetDateTime:类似ZonedDateTime
OffsetTime:带Offset的LocalTime
ChronoLocalDate:用于实现其他历法
ChronoLocalDateTime
最佳实践
Java处理日期和时间
1)java.util.Date同时表示日期和时间
2)java.sql.Date仅表示日期
3)java.sql.Time仅表示时间
4)java.sql.Timestamp表示数据库的TIMESTAMP类型
理解数据库类型到Java类型的映射
数据库 | 对应Java类(旧) | 对应Java类(新) |
---|---|---|
DATETIME | java.utilDate | LocalDateTime |
DATE | java.sql.Date | LocalDate |
TIME | java.sql.Time | LocalTime |
TIMESTAMP | java.sql.Timestamp | LocalDateTime |
新旧API的转换:通过long作为中介
新旧API时区转换
存储时刻最好使用long类型,可以编写格式化方法把long转换为用户本地时间
时间各种转换
将LocalDateTime转为自定义的时间格式的字符串
public static String getDateTimeAsString(LocalDateTime localDateTime, String format) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
return localDateTime.format(formatter);
}
将long类型的timestamp转为LocalDateTime
public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
}
将LocalDateTime转为long类型的timestamp
public static long getTimestampOfDateTime(LocalDateTime localDateTime) {
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
return instant.toEpochMilli();
}
将某时间字符串转为自定义时间格式的LocalDateTime
public static LocalDateTime parseStringToDateTime(String time, String format) {
DateTimeFormatter df = DateTimeFormatter.ofPattern(format);
return LocalDateTime.parse(time, df);
}
练习
通过System.currentMillis()可以获取当前的Epoch Time,以long类型表示,请编写一个方法,根据用户输入的时区,以yyyy-MM-dd HH:mm:ss的格式打印出本地日期和时间
public class WorldClock {
public static String getCurrentDateTime(String zoneId){
ZoneId zone = ZoneId.of(zoneId);
long currentTime = System.currentTimeMillis();
Instant instant = Instant.ofEpochMilli(currentTime);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return localDateTime.format(formatter);
}
}