Java处理日期时间API详解 较为详细的介绍了Java中处理日期时间的一些API,并有使用示例。
API介绍
日常开发和工作中,经常需要对时间日期进行处理,本文将介绍Java中是如何处理的。它里面有多种API可以使用,早期使用Date类,但是它是可变的存在设计缺陷,后又转而希望用Calendar类代替Date类,然而Calendar类也存在设计问题。后面又使用[LocalDateTime类](LocalDateTime类- CSDN搜索)来处理时间,他提供非常强大的功能。
日期时间类汇总
类名 | 功能 |
---|---|
java.util.Date | 提供了日期和时间的基本功能。表示特定的瞬间,精确到毫秒,但不包含时区信息 |
java.util.Calendar | 提供了更高级别的操作日期的功能,俗称日历类。它支持时区,格式化,还有日期和时间的加减运算 |
java.time.LocalDate | Jdk1.8引入,表示不含时间的日期(年、月、日) |
java.time.LocalTime | Jdk1.8引入,表示不含日期的时间(小时、分钟、秒) |
java.time.LocalDateTime | LocalDate 和LocalTime 的组合,表示带日期和时间的对象 |
java.time.ZonedDateTime | 表示带时区的日期和时间,可以指定不同的时区 |
java.time.Duration | 用于表示时间间隔的持续时间,精确到小时、分钟等单位 |
java.time.Period | 用于表示日期间隔的周期,精确到年、月、日等单位 |
日期时间操作类汇总
类名 | 功能 |
---|---|
java.text.SimpleDateFormat | DateFormat的具体实现类,它可以按照指定的模式将日期时间格式化为字符串,也可以将字符串解析为日期时间 |
java.time.format.DateTimeFormatter | Java 8引入的新类,用于格式化和解析日期时间对象。它提供了丰富的模式和选项,以便更灵活地处理不同的日期时间格式 |
java.util.Formatter | 这个类使用格式化字符串和参数,类似于C语言中的printf函数。它可以在输出中插入日期时间,并根据需要进行格式化 |
java.time.format.FormatStyle | 这个枚举类提供了一些预定义的日期、时间和日期时间格式的样式,例如SHORT、MEDIUM、LONG和FULL |
优缺点分析
类型 | 优点 | 缺点 |
---|---|---|
Date | 简单易懂,可以直接进行日期和时间操作; | 不够灵活,实现上存在线程安全问题;可变性; |
SimpleDateFormat | 可以根据指定模式对日期和时间进行格式化和解析; | 在多线程环境下不安全; |
Calendar | 可以处理更复杂的日期和时间操作,提供了丰富的方法和功能; | 使用起来较为繁琐,并且性能较差; |
DateTimeFormatter | 支持自定义的模式符号;线程安全;方法丰富; | 需要花费时间学习 |
LocalDateTime | 不受时区限制;不可变性和线程安全性;解析和格式化;操作丰富; | 缺乏时区信息 |
格式化规则(常用)
标识字母(区分大小写) | 含义 |
---|---|
y | 年 |
M | 月 |
d | 日 |
H | 时(24) |
h | 时(12) |
m | 分 |
s | 秒 |
S | 毫秒 |
Date
早期的日期时间处理类,但是大多方法已经过时,且难用;比如你想获取某月的第几天,单靠它几乎是不行的。
创建时间
Date date1 = new Date();//直接new是当前时间
//(直接打印固定CST中欧时间,但是Date并不支持时区)
//2024-12-26
System.out.println(date1);//Thu Dec 26 20:49:44 CST 2024
//2018-1-11
Date date2 = new Date(1515612156352L);//按1970年1月1日加上形参的时间戳的日期
System.out.println(date2);//Thu Jan 11 03:22:36 CST 2018
//2024-1-26
Date date3 = new Date(123,12,26);//从1900年往上加年份,从0开始计数,11代表十二月;需注意月份为12时会出错
System.out.println(date3);//Fri Jan 26 00:00:00 CST 2024
//2023-12-26
Date date4 = new Date(123,11,26,12,30,40);
System.out.println(date4);//Tue Dec 26 12:30:40 CST 2023
//2024-1-26
Date date5 = new Date(123,12,26);
System.out.println(date5);//Fri Jan 26 00:00:00 CST 2024
//2018-1-11
date5.setTime(1515612156352L);
System.out.println(date5);//Thu Jan 11 03:22:36 CST 2018
时间比较与格式化
格式化一般使用SimpleDateFormat来进行格式化,时间比较Date有getTime通过获取毫秒值(自1970年1月1日经历的毫秒数值)来比较;或者使用before,after,equals方法比较哪个日期早;还有一个compareTo方法。
//比较
System.out.println(date2.getTime() > date3.getTime());//false;直接比较毫秒值大小
// return obj instanceof Date & getTime() == ((Date) obj).getTime();
System.out.println(date3.equals(date5));//true;时间一样相等,重写了equals
System.out.println(date3.before(date4));//false;不在date4之前
System.out.println(date3.after(date1));//false;不在now之后
System.out.println(date3.compareTo(date5));//0;相等为0
System.out.println(date3.compareTo(date2));//1;大于为1
System.out.println(date3.compareTo(new Date()));//-1;小于为-1
//格式化
SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(simpleFormat.format(new Date()));//2024-12-30
try {
//Wed Dec 18 00:00:00 CST 2024
//解析为一个Date
System.out.println(simpleFormat.parse("2024-12-18"));
//Unparseable date: "2024/12/12"
//必须符合SimpleDateFormat实例化时的格式
System.out.println(simpleFormat.parse("2024/12/12"));
} catch (ParseException e) {
System.err.println(e.getMessage());
}
Calendar
有时候我们需要设置和获取日期数据的特定部分(时间的具体分量),比如说小时,日,或者分钟? 这就需要用到我们的Calendar(日历类),它比Date强大很多,有许多常量值。
常用常量值
字段值 | 含义 |
---|---|
YEAR | 年 |
MONTH | 月(从0开始,显示时需+1处理) |
DATE | 天 |
DAY_OF_YEAR | 一年中的第几天 |
DAY_OF_MONTH | 一月中的第几天 |
DAY_OF_WEEK | 一周中的第几天(周几,周日为1) |
HOUR | 时(12小时制) |
HOUR_OF_DAY | 时(24小时制) |
MINUTE | 分 |
SECOND | 秒 |
常用方法
获取时间信息
方法 | 作用 |
---|---|
get(int field) | 返回给定字段(field;常量)的值,例如Calendar.YEAR 表示年份 |
getTime() | 返回表示当前时间的一个Date对象 |
getTimeInMillis() | 返回表示当前时间的一个时间戳,以毫秒为单位 |
getActualMaximum(int field) | 返回指定字段(field)的最大允许值 |
getActualMinimum(int field) | 返回指定字段(field)的最小允许值 |
getDisplayName(int field, int style, Locale locale) | 返回指定字段(field)的本地化名称。可以根据所需的语言环境(Locale)和样式(style)获取字段的可读名称 |
设置时间日期
方法 | 作用 |
---|---|
set(int field, int value) | 设置给定字段(field)的值为指定的值(value) |
add(int field, int amount) | 将指定字段(field)的值增加指定的数量(amount)。可以实现对日期和时间的增减操作 |
setTime(Date date) | 将对象的值设置为给定日期(Date)所代表的时间 |
roll(int field, boolean up) | 将指定字段(field)的值“滚动”,即在不改变更大字段的情况下增减指定字段的值 |
创建时间
一般就是通过获取实例,然后调用get,set,add等方法传入那些时间类型常量来进行操作。注意:月份是从0开始。
Calendar是抽象类,不能被实例化,要通过getInstance获取当前时间实例
//Calendar是抽象类,不能被实例化,要通过getInstance获取当前时间实例
Calendar calendar = Calendar.getInstance();
//获取年月日
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int date = calendar.get(Calendar.DATE);
//2024年12月30日
System.out.println(year + "年" + month + "月" + date + "日");
//设置年月日
calendar.set(Calendar.YEAR,2024);
calendar.set(Calendar.MONTH,11);
calendar.set(Calendar.DATE,31);
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH) + 1;
date = calendar.get(Calendar.DATE);
//2024年12月31日
System.out.println(year + "年" + month + "月" + date + "日");
calendar.add(Calendar.DATE,1);//+1天
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH) + 1;
date = calendar.get(Calendar.DATE);
//2025年1月1日;祝看到这的小伙伴2025新年快乐
System.out.println(year + "年" + month + "月" + date + "日");
System.out.println(calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.getDefault()));//星期三
calendar.add(Calendar.YEAR,-1);//要减少就传负数
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH) + 1;
date = calendar.get(Calendar.DATE);
//2024年1月1日;祝看到这的小伙伴2025新年快乐
System.out.println(year + "年" + month + "月" + date + "日");
转换Date与比较
比较与Date类似,都有after,before等方法,clear方法是清除所有字段的值,将Calendar对象重置为初始状态。
//与Date转换
Date time = calendar.getTime();
System.out.println(time);//Mon Jan 01 01:54:02 CST 2024
calendar.setTime(new Date());
System.out.println(calendar);//java.util.GregorianCalendar[time=1735494842180,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=31,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2024,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=365,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=1,HOUR_OF_DAY=1,MINUTE=54,SECOND=2,MILLISECOND=180,ZONE_OFFSET=28800000,DST_OFFSET=0]
//比较
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
Calendar c3 = Calendar.getInstance();
c1.set(2024,0,1);
c2.set(2025,0,1);
System.out.println(calendar.before(c1));//false,不是在c1之前
System.out.println(calendar.equals(c3));//true,重写equals
System.out.println(calendar.after(c2));//false,不是在c2之后
System.out.println(calendar.compareTo(c3));//0;相等
System.out.println(calendar.compareTo(c2));//-1;小于c2
System.out.println(calendar.compareTo(c1));//1;大于c1
//将日历对象的值清空
calendar.clear();
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH) + 1;
date = calendar.get(Calendar.DATE);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
//1970年1月1日0时0分0秒
System.out.println(year + "年" + month + "月" + date + "日" + hour + "时" + minute + "分" + second + "秒");
LocalDateTime
包含年月日时分秒,是LocalDate(年月日)和LocalTime(时分秒)的结合体。它不包含时区信息,如果需要使用到时区可以看接下来的ZonedDateTime;
常用方法
创建LocalDateTime对象
方法 | 作用 |
---|---|
now() | 返回当前日期时间 |
now(ZoneId zone) | 返回指定时区的当前日期时间 |
of(int year, Month month, int dayOfMonth, int hour, int minute) | 创建指定日期时间的对象 |
of(LocalDate date, LocalTime time) | 根据指定的日期和时间创建对象 |
parse(CharSequence text) | 将指定字符串解析为对象 |
获取日期时间信息
方法 | 作用 |
---|---|
LocalDate toLocalDate() | 返回日期部分 |
LocalTime toLocalTime() | 返回时间部分 |
int getYear() | 返回年份 |
Month getMonth() | 返回月份 |
int getMonthValue() | 返回月份值 |
int getDayOfMonth() | 返回月份中的天数 |
int getHour() | 返回小时数 |
int getMinute() | 返回分钟数 |
int getSecond() | 返回秒数 |
int getNano() | 返回纳秒数 |
boolean isAfter(LocalDateTime other) | 检查当前日期时间是否在指定日期时间之后 |
boolean isBefore(LocalDateTime other) | 检查当前日期时间是否在指定日期时间之前 |
boolean isEqual(LocalDateTime other) | 检查当前日期时间是否与指定日期时间相等 |
时间操作
方法 | 作用 |
---|---|
plusYears(long years) | 将指定的年数加到当前日期时间 |
plusMonths(long months) | 将指定的月数加到当前日期时间 |
plusWeeks(long weeks) | 将指定的周数加到当前日期时间 |
plusDays(long days) | 将指定的天数加到当前日期时间 |
plusHours(long hours) | 将指定的小时数加到当前日期时间 |
plusMinutes(long minutes) | 将指定的分钟数加到当前日期时间 |
plusSeconds(long seconds) | 将指定的秒数加到当前日期时间 |
plusNanos(long nanos) | 将指定的纳秒数加到当前日期时间 |
minusYears(long years) | 将指定的年数从当前日期时间中减去 |
minusMonths(long months) | 将指定的月数从当前日期时间中减去 |
minusWeeks(long weeks) | 将指定的周数从当前日期时间中减去 |
minusDays(long days) | 将指定的天数从当前日期时间中减去 |
minusHours(long hours) | 将指定的小时数从当前日期时间中减去 |
minusMinutes(long minutes) | 将指定的分钟数从当前日期时间中减去 |
minusSeconds(long seconds) | 将指定的秒数从当前日期时间中减去 |
minusNanos(long nanos) | 将指定的纳秒数从当前日期时间中减去 |
其他操作
方法 | 作用 |
---|---|
boolean isSupported(TemporalField field) | 检查指定字段是否支持日期时间 |
String format(DateTimeFormatter formatter) | 将日期时间格式化为字符串 |
boolean isSupported(ChronoUnit unit) | 检查指定单位是否支持日期时间间隔计算 |
long until(Temporal endExclusive, TemporalUnit unit) | 计算当前日期时间与指定日期时间之间的时间间隔 |
创建时间
//当前时间
LocalDateTime now = LocalDateTime.now();
//2024-12-30T23:44:52.406
System.out.println(now);
//指定时区的当前时间
LocalDateTime zoneNow = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
//2024-12-30T23:44:52.407
System.out.println(zoneNow);
//指定日期时间
LocalDateTime lastDate = LocalDateTime.of(2024, 12, 31, 23, 59);
//2024-12-31T23:59
System.out.println(lastDate);
lastDate = LocalDateTime.of(2024, Month.DECEMBER,31,23,59);//这是月份的一个枚举
//2024-12-31T23:59
System.out.println(lastDate);
//使用 LocalDate 和 LocalTime创建
LocalDate localDate = LocalDate.of(2024, Month.DECEMBER, 31);
LocalTime localTime = LocalTime.of(23, 59);
lastDate = LocalDateTime.of(localDate, localTime);
//2024-12-31T23:59
System.out.println(lastDate);
// 将指定字符串解析为LocalDateTime对象
String dateString = "2025-01-01 00:00:00";
LocalDateTime parsedDateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//2025-01-01T00:00
System.out.println(parsedDateTime);
//可以由LocalDate和LocalTime组成,也可以拆开
localDate = lastDate.toLocalDate();
localTime = lastDate.toLocalTime();
//2024-12-31
System.out.println(localDate);
//23:59
System.out.println(localTime);
//获取年份
System.out.println("年份: " + lastDate.getYear());//年份: 2024
//获取月份枚举
System.out.println("月份: " + lastDate.getMonth());//月份: DECEMBER
//获取月份值
System.out.println("月份值: " + lastDate.getMonthValue());//月份值: 12
//获取这是这个月的第几天
System.out.println("月份中的天数: " + lastDate.getDayOfMonth());//月份中的天数: 31
//获取小时
System.out.println("小时数: " + lastDate.getHour());//小时数: 23
//获取分钟
System.out.println("分钟数: " + lastDate.getMinute());//分钟数: 59
//获取秒数
System.out.println("秒数: " + lastDate.getSecond());//秒数: 0
//获取纳秒
System.out.println("纳秒数: " + lastDate.getNano());//纳秒数: 0
比较与其他操作
该类有isAfter,isBefore,isEqual方法来比较两个日期时间的值。格式化一般使用DateTimeFormatte与下面日期和时间部分一起介绍。
LocalDateTime newYear = LocalDateTime.of(2025, 1, 1, 0, 0);
//2025-01-01T00:00
System.out.println(newYear);
//该时间在传入的参数时间(之后/之前/相等)?
System.out.println(newYear.isAfter(lastDate));//true
System.out.println(newYear.isBefore(lastDate));//false
System.out.println(newYear.isEqual(lastDate));//false
//日期加减操作
System.out.println(newYear.plusYears(1));//2026-01-01T00:00
System.out.println(newYear.minusDays(1));//2024-12-31T00:00
System.out.println(newYear.minusMinutes(1));//2024-12-31T23:59
//两个日期时间的间隔
System.out.println(newYear.until(newYear.plusYears(1), ChronoUnit.DAYS));//365
//参数日期比较早的是负数,晚的是正数;不足时间单位表示的为0
System.out.println(newYear.until(lastDate, ChronoUnit.YEARS));//0
System.out.println(newYear.until(lastDate, ChronoUnit.MONTHS));//0
System.out.println(newYear.until(lastDate, ChronoUnit.DAYS));//0
System.out.println(newYear.until(lastDate, ChronoUnit.HOURS));//0
System.out.println(newYear.until(lastDate, ChronoUnit.MINUTES));//-1
System.out.println(newYear.until(lastDate, ChronoUnit.SECONDS));//-60
LocalDate与LocalTime
它们的创建与LocalDateTime类似,这里就不过多赘述了。
使用对应的of方法和parse方法就可以创建对应时间日期对象。
//1.1 通过of重载的工厂方法创建
LocalDate ofDate = LocalDate.of(2024, 5, 20);//2024-05-20
LocalTime ofTime = LocalTime.of(13, 14, 20); // 13:14:20
//1.2 使用静态方法parse来创建
LocalDate parseDate = LocalDate.parse("2024-05-20");//2014-03-18
LocalTime parseTime = LocalTime.parse("13:14:20");// 13:45:20
//2024-05-20T00:00
System.out.println(ofDate.atStartOfDay());//清空时分秒,获取当天0时0分0秒的LocalDateTime
//互相合并为LocalDateTime
LocalDateTime dt4 = ofDate.atTime(ofTime);
LocalDateTime dt5 = ofTime.atDate(ofDate);
System.out.println(ofDate.get(ChronoField.YEAR));//2024
System.out.println(ofDate.get(ChronoField.MONTH_OF_YEAR));//5
System.out.println(ofDate.get(ChronoField.DAY_OF_MONTH));//20
System.out.println(ofDate.getDayOfMonth());//20
System.out.println(ofDate.lengthOfMonth());//31(该月有多少天)
System.out.println(ofDate.isLeapYear());//true (闰年)
System.out.println(ofTime.get(ChronoField.HOUR_OF_DAY));//13
System.out.println(ofTime.get(ChronoField.MINUTE_OF_HOUR));//14
System.out.println(ofTime.get(ChronoField.SECOND_OF_MINUTE));//20
//ChronoUnit也可以计算两个单元之间的天数、月数或年数
LocalDate start = LocalDate.of(2025,1,1);
LocalDate end = LocalDate.of(2026,1,1);
//相差天数:365
System.out.println("相差天数:" + ChronoUnit.DAYS.between(start , end ));
//相差月数:12
System.out.println("相差月数:" + ChronoUnit.MONTHS.between(start , end ));
//相差年数:1
System.out.println("相差年数:" + ChronoUnit.YEARS.between(start , end ));
LocalDate today = LocalDate.now();
//获取当前月第一天:
System.out.println(today.with(TemporalAdjusters.firstDayOfMonth()));//2024-12-01
// 取本月最后一天
System.out.println(today.with(TemporalAdjusters.lastDayOfMonth()));//2024-12-31
//当年最后一天
System.out.println(today.with(TemporalAdjusters.lastDayOfYear()));//2024-12-31
//2024年最后一个周日
System.out.println(LocalDate.parse("2024-12-31").with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY)));//2024-12-29
//ChronoUnit常量计算时间间隔
LocalTime gettimeStart = LocalTime.parse("00:01:40");
LocalTime gettimeEnd = LocalTime.parse("00:03:20");
System.out.println("相差: "+HOURS.between(gettimeStart, gettimeEnd)+"小时");//相差: 0小时
System.out.println("相差: "+MINUTES.between(gettimeStart, gettimeEnd)+"分钟");//相差: 1分钟
System.out.println("相差: "+SECONDS.between(gettimeStart, gettimeEnd)+"秒");//相差: 100秒
与时间戳的转换
LocalDateTime需要指定时区然后转成ZonedDateTime,然后再转成时间戳。
LocalDateTime localDateTime = LocalDateTime.now();
Timestamp ts = Timestamp.valueOf(localDateTime);
//转为毫秒级时间戳
//先转成java.sql.timestamp
System.out.println(ts.getTime());//1735647821836
//转成ZonedDateTime获取instant然后得到时间戳
System.out.println(localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());//1735647821836
//转为秒级时间戳
System.out.println(ts.toInstant().getEpochSecond());//1735647821
ZonedDateTime常用方法与时区
withZoneSameInstant方法常用于时间的时区转换,推荐使用。ZoneId是被用来处理时区的,与zoneddatetime相配合可以很方便的处理不同时区的时间。
方法名称 | 描述 |
---|---|
of(String zoneId) | 根据时区标识符创建 ZoneId 对象。 |
getAvailableZoneIds() | 获取一组可用的区域ID。 |
getDisplayName(TextStyle style, Locale locale) | 获取区域的文字表示,例如“英国时间”或“+02:00”。 |
getId() | 获取唯一的时区ID。 |
getRules() | 获取此ID的时区规则,允许执行计算。 |
hashCode() | 此时区ID的哈希码。 |
normalized() | 规范时区ID,尽可能返回 ZoneOffset 。 |
of(String zoneId, Map<String,String> aliasMap) | 使用其ID使用别名映射来补充标准区域ID获取 ZoneId 实例。 |
ofOffset(String prefix, ZoneOffset offset) | 获得一个封装偏移量的 ZoneId 实例。 |
systemDefault() | 获取系统默认时区。 |
toString() | 使用ID将该区域输出为 String 。 |
方法名称 | 描述 |
---|---|
withZoneSameInstant(ZoneId zone) | 将 ZonedDateTime 对象转换为指定时区的日期时间,保持瞬间不变。 |
withEarlierOffsetAtOverlap() | 在夏令时转换期间,选择较早的偏移量。 |
withLaterOffsetAtOverlap() | 在夏令时转换期间,选择较晚的偏移量。 |
toLocalDateTime() | 返回不带时区信息的 LocalDateTime 对象。 |
toLocalDate() | 返回不带时区信息的 LocalDate 对象。 |
toLocalTime() | 返回不带日期信息的 LocalTime 对象。 |
toOffsetDateTime() | 返回带时区偏移量的 OffsetDateTime 对象。 |
getZone() | 返回 ZonedDateTime 对象的时区信息。 |
toInstant() | 将 ZonedDateTime 对象转换为一个 Instant 对象。 |
format(DateTimeFormatter formatter) | 使用指定的 DateTimeFormatter 格式化 ZonedDateTime 对象。 |
isSupported(TemporalField field) | 检查指定的日期时间字段是否支持。 |
get(TemporalField field) | 获取指定的日期时间字段值。 |
plus(long amountToAdd, TemporalUnit unit) | 在 ZonedDateTime 对象上增加指定的时间量。 |
minus(long amountToSubtract, TemporalUnit unit) | 在 ZonedDateTime 对象上减去指定的时间量。 |
truncatedTo(TemporalUnit unit) | 将 ZonedDateTime 对象截断到指定的时间单位。 |
equals(Object other) | 比较两个 ZonedDateTime 对象是否相等。 |
hashCode() | 返回 ZonedDateTime 对象的哈希码。 |
compareTo(ZonedDateTime other) | 比较两个 ZonedDateTime 对象的先后顺序。 |
两个时区时间的转换
这是一个时区转换简单示例,并计算该月初与月末的时间戳。
//用户时区
ZoneId zoneIdOfUser = ZoneId.of(ZoneId.systemDefault().toString());
LocalDate userStartDate = LocalDate.of(lastDate.getYear(),lastDate.getMonth(),1);
LocalDate userEndDate = LocalDate.of(localDate.getYear(),lastDate.getMonth(),userStartDate.lengthOfMonth());
LocalDateTime atStartOfDay = userStartDate.atStartOfDay();
LocalDateTime atEndOfDay = LocalDateTime.of(userEndDate, LocalTime.of(23, 59, 59))
.with(ChronoField.NANO_OF_SECOND, 999999999);
ZonedDateTime userZoneStartDay = atStartOfDay.atZone(zoneIdOfUser);
ZonedDateTime userZoneEndDay = atEndOfDay.atZone(zoneIdOfUser);
//系统时区
ZoneId sysZoneId = ZoneId.systemDefault();
long startTime = userZoneStartDay.withZoneSameInstant(sysZoneId).toInstant().toEpochMilli();
long endTime = userZoneEndDay.withZoneSameInstant(sysZoneId).toInstant().toEpochMilli();
时间区间:Duration和Period
Duration类主要用于以秒和纳秒衡量时间的长短。
Period类以年、月或者日的方式对多个时间单位建模。
Duration 类常用方法
方法名称 | 描述 |
---|---|
ofDays(long days) | 创建一个表示特定天数的 Duration 。 |
ofHours(long hours) | 创建一个表示特定小时数的 Duration 。 |
ofMinutes(long minutes) | 创建一个表示特定分钟数的 Duration 。 |
ofSeconds(long seconds) | 创建一个表示特定秒数的 Duration 。 |
ofMillis(long millis) | 创建一个表示特定毫秒数的 Duration 。 |
ofNanos(long nanos) | 创建一个表示特定纳秒数的 Duration 。 |
between(Temporal start, Temporal end) | 静态方法,返回一个 Duration 对象,表示两个时间点之间的间隔。 |
plus(Duration other) | 返回一个加上指定 Duration 后的新的 Duration 。 |
minus(Duration other) | 返回一个减去指定 Duration 后的新的 Duration 。 |
multipliedBy(long multiplier) | 返回一个乘以指定数值后的新的 Duration 。 |
dividedBy(long divisor) | 返回一个除以指定数值后的新的 Duration 。 |
toDays() | 将 Duration 转换为天数。 |
toHours() | 将 Duration 转换为小时数。 |
toMinutes() | 将 Duration 转换为分钟数。 |
toSeconds() | 将 Duration 转换为秒数。 |
toMillis() | 将 Duration 转换为毫秒数。 |
toNanos() | 将 Duration 转换为纳秒数。 |
addTo(Instant instant) | 将 Duration 加到指定的 Instant 上。 |
addTo(LocalDateTime dateTime) | 将 Duration 加到指定的 LocalDateTime 上。 |
subtractFrom(Instant instant) | 从指定的 Instant 减去 Duration 。 |
subtractFrom(LocalDateTime dateTime) | 从指定的 LocalDateTime 减去 Duration 。 |
Period 类常用方法
方法名称 | 描述 |
---|---|
of(int years, int months, int days) | 创建一个表示特定年、月、天的 Period 。 |
ofYears(int years) | 创建一个表示特定年数的 Period 。 |
ofMonths(int months) | 创建一个表示特定月数的 Period 。 |
ofDays(int days) | 创建一个表示特定天数的 Period 。 |
between(LocalDate startInclusive, LocalDate endExclusive) | 静态方法,返回一个 Period 对象,表示两个日期之间的间隔。 |
plus(Period other) | 返回一个加上指定 Period 后的新的 Period 。 |
minus(Period other) | 返回一个减去指定 Period 后的新的 Period 。 |
multipliedBy(int multiplier) | 返回一个乘以指定数值后的新的 Period 。 |
dividedBy(int divisor) | 返回一个除以指定数值后的新的 Period 。 |
toTotalMonths() | 将 Period 转换为总月数。 |
addTo(LocalDate date) | 将 Period 加到指定的 LocalDate 上。 |
addTo(LocalDateTime dateTime) | 将 Period 加到指定的 LocalDateTime 上。 |
subtractFrom(LocalDate date) | 从指定的 LocalDate 减去 Period 。 |
subtractFrom(LocalDateTime dateTime) | 从指定的 LocalDateTime 减去 Period 。 |
LocalDateTime parseStart = LocalDateTime.parse("2022-12-03T10:15:30");
LocalDateTime parseEnd = LocalDateTime.parse("2023-12-01T10:25:33");
//between的用法是end-start的时间,若start的时间大于end的时间,则所有的值是负的
Duration duration = Duration.between(parseStart, parseEnd);
String timeString = duration.toString(); //此持续时间的字符串表示形式,使用基于ISO-8601秒*的表示形式,例如 PT8H6M12.345S
System.out.println("相差的天数="+duration.toDays());//相差的天数=363
System.out.println("相差的小时="+ duration.toHours());//相差的小时=8712
System.out.println("相差的分钟="+duration.toMinutes());//相差的分钟=522730
System.out.println("相差的毫秒="+duration.toMillis());//相差的毫秒=31363803000
System.out.println("相差的纳秒="+duration.toNanos());//相差的纳秒=31363803000000000
System.out.println("timeString时间="+timeString);//timeString时间=PT8712H10M3S
//isNegative返回Duration实例对象是否为负
System.out.println(Duration.between(parseStart, parseEnd).isNegative());//false end-start为正,所以此处返回false
System.out.println(Duration.between(parseEnd, parseStart).isNegative());//true start-end为负,所以此处返回true
System.out.println(Duration.between(parseStart, parseStart).isNegative());//false start-start为0,所以此处为false
Period period = Period.between(start,end);
//两个时间之间的差值 年:1,月:0,日:0
System.out.println("两个时间之间的差值 年:"+period.getYears()+",月:"+period.getMonths()+",日:"+period.getDays());
结尾
以上就是我整理的一些Java处理日期时间的API,如有不足请见谅。从Date到Calendar到LoaclDateTime,提供的API越来越强大,使得我们处理时间的方式变得简单,而且补足了之前的设计缺陷。后续开发中,推荐使用新版日期API。