java8之LocalDate的使用、LocalDate格式化问题
前言
Java 8里面添加了许多的新特性,其中一个最常见也是最实用的便是日期处理的类——LocalDate。
新增的日期类主要有三种:
- java.time.LocalDate ->只对年月日做出处理
- java.time.LocalTime ->只对时分秒纳秒做出处理
- java.time.LocalDateTime ->同时可以处理年月日和时分秒
LocalDate:默认返回一个日期格式为yyyy-MM-dd格式的日期
一:创建LocalDate
方法 | 说明 |
---|---|
static LocalDate now() | 获取默认时区的当前日期,默认返回格式yyyy-MM-dd |
static LocalDate now(Clock clock) | 从指定时钟获取当前日期 |
static LocalDate now(ZoneId zone) | 获取指定时区的当前日期 |
static LocalDate of(int year, int month, int dayOfMonth) | 根据指定的年、月、日获取LocalDate 实例 |
static LocalDate of(int year, Month month, int dayOfMonth) | 根据指定的年、月、日获取LocalDate 实例 |
static LocalDate ofYearDay(int year,int dayOfYear) | 根据指定的年,年中的第xx天获取LocalDate实例 |
static LocalDate ofEpochDay(long epochDay) | 从1970-01-01开始获取指定天数的LocalDate实例 |
static LocalDate parse(CharSequence text) | 将字符串转换为LocalDate,字符串的格式必须为yyyy-MM-dd 10位长度的日期格式,否则会报错 |
static LocalDate parse(CharSequence text, DateTimeFormatter formatter) | 将text字符串转换为formatter格式,text的格式必须与formatter格式一致,如text为yyyyMMdd格式,则formatter也应该为yyyyMMdd格式,否则会报错 |
1、now()
从默认时区的系统时钟中获取当前日期。默认输出格式为yyyy-MM-dd
LocalDate localDate = LocalDate.now();
System.out.println(localDate);
2021-11-29
2、now(Clock clock)
从指定时钟获取当前日期。
LocalDate l = LocalDate.now(Clock.systemDefaultZone());
System.out.println(l);
System.out.println(Clock.systemDefaultZone());//方法返回带有系统默认时区的Clock实例。
System.out.println(Clock.systemUTC());//此方法返回带有UTC时区的Clock实例。
2021-11-29
SystemClock[Asia/Shanghai]
SystemClock[Z]
3、now(ZoneId zone)
从指定时区的系统时钟中获取当前日期。
LocalDate l = LocalDate.now(ZoneId.of("UTC+1"));
System.out.println(l);
2021-11-29
时区是用ZoneId类表示的,你可以使用ZoneId.now()或ZoneId.of(“xxx”)来实例化:
ZoneId zoneId = ZoneId.of("UTC+1");
传给of()方法的参数是时区的ID,如“UTC+1”指距离UTC(格林威治时间)有一小时的时差,你可以使用你想要的时差来表示ZoneId(如+1与-5等等)
你也可以使用另一种方式表示zone id,即使用地区名字,也是可以的:
ZoneId zoneId2 = ZoneId.of("Europe/Copenhagen");
ZoneId zoneId3 = ZoneId.of("Europe/Paris");
4、of(int year, int month, int dayOfMonth)
从年、月和日获取LocalDate实例
LocalDate l = LocalDate.of(2021, 11, 29);
System.out.println(l);
2021-11-29
5、ofYearDay(int year,int dayOfYear)
从指定年的指定天获取LocalDate实例
//获取2021年第230天的日期
LocalDate l = LocalDate.ofYearDay(2021, 230);
System.out.println(l);
2021-08-18
6、ofEpochDay(long epochDay)
从1970-01-01开始获取指定天数的LocalDate实例
LocalDate l = LocalDate.ofEpochDay(0);//1970-01-01
LocalDate l1 = LocalDate.ofEpochDay(-10);//1969-12-22
LocalDate l2 = LocalDate.ofEpochDay(10);//1970-01-11
7、parse(CharSequence text)
将字符串转换为LocalDate,字符串的格式必须为yyyy-MM-dd 10位长度的日期格式,否则会报错,字符串必须是一个合法的日期,否则会报错
LocalDate l = LocalDate.parse("2021-01-29");
System.out.println(l); //2021-01-29
错误示例:
//日期格式非yyyy-MM-dd
LocalDate l = LocalDate.parse("2021-1-29");
//日期格式非yyyy-MM-dd
LocalDate l = LocalDate.parse("2021/01/29");
//字符串不是一个合法的日期,2月没有30号
LocalDate l = LocalDate.parse("2021-02-30");
若parse(CharSequence text)中传入的格式非yyyy-MM-dd或不合法,会抛出异常,且长度需要是10位
Exception in thread "main" java.time.format.DateTimeParseException: Text '2021/11/29' could not be parsed at index 4
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalDate.parse(LocalDate.java:428)
at java.base/java.time.LocalDate.parse(LocalDate.java:413)
at com.aexpec.mic.merchant.controller.Test.main(Test.java:19)
8、parse(CharSequence text, DateTimeFormatter formatter)
将text字符串转换为formatter格式,text的格式必须与formatter格式一致,如text为yyyyMMdd格式,则formatter也应该为yyyyMMdd格式,否则会报错
LocalDate l = LocalDate.parse("2021-11-29", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
LocalDate localDate1 = LocalDate.parse("20211129", DateTimeFormatter.ofPattern("yyyyMMdd"));
System.out.println(l);
System.out.println(localDate1);
2021-11-29
2021-11-29
- 为什么localDate1输出后格式为yyyy-MM-dd?
- 虽然入参格式为yyyyMMdd,但是转换为LocalDate后,格式默认为yyyy-MM-dd, LocalDate返回的格式默认为yyyy-MM-dd,下面会讲如何转换为其他格式。
错误示例:
//错误示例:text与formatter格式不一致,会抛出异常
LocalDate l = LocalDate.parse("2021-11-29", DateTimeFormatter.ofPattern("yyyyMMdd"));
LocalDate localDate1 = LocalDate.parse("20211129", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
二:LocalDate日期比较
方法 | 说明 |
---|---|
boolean isBefore(ChronoLocalDate other) | 检查日期是否在指定日期之前 |
boolean isAfter(ChronoLocalDate other) | 检查日期是否在指定日期之后 |
boolean isEqual(ChronoLocalDate other) | 比较日期是否相同 |
int compareTo(ChronoLocalDate other) | 日期比较localDateA.compareTo(localDateB),若相等返回0;若A>B,返回1 ;若A<B返回-1 |
1、boolean isBefore(ChronoLocalDate other)
用于检查此LocalDate值是否在给定的ChronoLocalDate(other)之前
LocalDate l = LocalDate.parse("2021-11-29");
System.out.println(l.isBefore(LocalDate.parse("2021-11-28"))); //false
System.out.println(l.isBefore(LocalDate.parse("2021-11-30"))); //true
2、boolean isAfter(ChronoLocalDate other)
用于检查此LocalDate值是否在给定的ChronoLocalDate(other)之后
LocalDate l = LocalDate.parse("2021-11-29");
System.out.println(l.isAfter(LocalDate.parse("2021-11-28"))); //true
System.out.println(l.isAfter(LocalDate.parse("2021-11-30"))); //false
3、boolean isEqual(ChronoLocalDate other)
用于检查此LocalDate值是否与给定的ChronoLocalDate(other)相等
LocalDate l = LocalDate.parse("2021-11-29");
System.out.println(l.isEqual(LocalDate.parse("2021-11-28"))); //false
System.out.println(l.isEqual(LocalDate.parse("2021-11-30"))); //false
System.out.println(l.isEqual(l)); //true
4、int compareTo(ChronoLocalDate other)
比较两个日期A.compareTo(B),若日期相同则返回0;
- 若A>B,则返回1;
- 若A<B,则返回-1;
LocalDate l = LocalDate.parse("2021-11-29");
System.out.println(l.compareTo(LocalDate.parse("2021-11-28"))); //1
System.out.println(l.compareTo(LocalDate.parse("2021-11-30"))); //-1
System.out.println(l.compareTo(l)); //0
三:获取年、月、日
方法 | 说明 |
---|---|
int getYear() | 获取年份 |
Month getMonth() | 使用月枚举类型获取月份 |
int getMonthValue() | 返回数字月份 1-12月 |
int getDayOfMonth() | 获取日期在该月是第几天 |
DayOfWeek getDayOfWeek() | 获取日期是星期几 |
int getDayOfYear() | 获取日期在该年是第几天 |
boolean isLeapYear() | 检查是否闰年 |
int lengthOfMonth() | 返回日期所在月份共有几天 |
int lengthOfYear() | 返回日期所在年份共有几天 |
long toEpochDay() | 返回当前日期距离1970年1月1日的天数 |
LocalDate localDate = LocalDate.now();
System.out.println(localDate); // 2021-11-29
System.out.println("年 : " + localDate.getYear()); // 2021
System.out.println("月(英文) : " + localDate.getMonth()); // NOVEMBER
System.out.println("月(数字英文): " + localDate.getMonth().getValue()); // 11
System.out.println("月(数字英文): " + localDate.getMonthValue()); // 11
System.out.println("本月第几天 : " + localDate.getDayOfMonth()); // 29
System.out.println("星期几(英文) : " + localDate.getDayOfWeek()); // MONDAY
System.out.println("星期几(数字英文) : " + localDate.getDayOfWeek().getValue()); // 1
System.out.println("本年的第几天 : " + localDate.getDayOfYear()); // 333
System.out.println("是否润年 : " + localDate.isLeapYear()); // false
System.out.println("本月天数 : " + localDate.lengthOfMonth()); // 30
System.out.println("本年天数 : " + localDate.lengthOfYear()); // 365
四:日期计算,加/减年、月、周、日
4.1、加/减年、月、周、日
方法 | 说明 |
---|---|
LocalDate plus(long amountToAdd, TemporalUnit unit) | 通用方法,可以通过unit参数控制增加天、周、月、年 |
LocalDate plusDays(long daysToAdd) | 返回增加了*天的LocalDate副本 |
LocalDate plusWeeks(long weeksToAdd) | 返回增加了*周的LocalDate副本 |
LocalDate plusMonths(long monthsToAdd) | 返回增加了*月的LocalDate副本 |
LocalDate plusYears(long yearsToAdd) | 返回增加了*年的LocalDate副本 |
LocalDate minus(long amountToAdd, TemporalUnit unit) | 通用方法,可以通过unit参数控制减少天、周、月、年 |
LocalDate minusDays(long daysToSubtract) | 返回减少了*天的LocalDate副本 |
LocalDate minusWeeks(long weeksToSubtract) | 返回减少了*周的LocalDate副本 |
LocalDate minusMonths(long monthsToSubtract) | 返回减少了*月的LocalDate副本 |
LocalDate minusYears(long yearsToSubtract) | 返回减少了*年的LocalDate副本 |
LocalDate localDate1 = LocalDate.now();
localDate1 = LocalDate.parse("2021-11-29");
System.out.println(localDate1); // 2021-11-29
//通用方法
System.out.println("增加 : " + localDate1.plus(1, ChronoUnit.DAYS));
System.out.println("增加天数 : " + localDate1.plusDays(1)); // 2021-11-30
System.out.println("增加周数 : " + localDate1.plusWeeks(1)); // 2021-12-06
System.out.println("增加月数 : " + localDate1.plusMonths(1)); // 2021-12-29
System.out.println("增加年数 : " + localDate1.plusYears(1)); // 2022-11-29
//通用方法
System.out.println("减少 : " + localDate1.minus(1, ChronoUnit.DAYS));
System.out.println("减少天数 : " + localDate1.minusDays(1)); // 2021-11-28
System.out.println("减少月数 : " + localDate1.minusMonths(1)); // 2021-10-29
System.out.println("减少周数 : " + localDate1.minusWeeks(1)); // 2021-11-22
System.out.println("减少年数 : " + localDate1.minusYears(1)); // 2020-11-29
以上方法返回的都是LocalDate实例的副本,即源对象localDate1变量的值不变
4.2、计算两个日期的间隔
方法一:计算两个日期相差的天数
- 调用LocalDate类的toEpochDay方法,返回距离1970年1月1日的long值
- 此方法只能计算两个日期相差的天数,不能计算月数,年数
LocalDate start = LocalDate.of(2020,2,28);
LocalDate end = LocalDate.of(2021,12,3);
System.out.println("两个时间之间的相差的天数: "+(end.toEpochDay()-start.toEpochDay())); //644
方法二::计算两个日期相差的天数、月数、年数
ChronoUnit也可以计算两个单元之间的天数、月数或年数。
我们使用ChronoUnit类的between() 方法来执行相同的操作:
LocalDate start = LocalDate.of(2020,2,28);
LocalDate end = LocalDate.of(2021,12,3);
long days= ChronoUnit.DAYS.between(start , end );
结果:644
long month= ChronoUnit.MONTHS.between(start , end );
结果21
long year= ChronoUnit.YEARS.between(start , end );
结果 1
方法三: 计算两个日期相差的年月日
此方法主要是计算两个日期相差的年月日,不能计算出具体相差了多少天
LocalDate start = LocalDate.of(2020,2,28);
LocalDate end = LocalDate.of(2021,12,3);
Period period = Period.between(start,end);
System.out.println("两个时间之间的差值 年:"+period.getYears()+",月:"+period.getMonths()+",日:"+period.getDays());
两个时间之间的差值 年:1,月:9,日:5
五:日期格式化
方法 | 说明 |
---|---|
String format(DateTimeFormatter formatter) | 使用特定格式化形式将LocalDate转为字符串 |
static LocalDate parse(CharSequence text) | 从文本字符串获取LocalDate实例,text必须是yyyy-MM-dd格式 |
static LocalDate parse(CharSequence text, DateTimeFormatter formatter) | 使用特定格式化形式从文本字符串获取LocalDate实例,text的格式必须与formatter格式一致,如text为yyyyMMdd格式,则formatter也应该为yyyyMMdd格式,否则会报错 |
LocalDate l = LocalDate.parse("2021-01-29");
System.out.println(l); //2021-01-29
LocalDate l1 = LocalDate.parse("2021-11-29", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(l1); //2021-11-29
LocalDate localDate1 = LocalDate.parse("20211129", DateTimeFormatter.ofPattern("yyyyMMdd"));
System.out.println(localDate1); //2021-11-29
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
System.out.println(l.format(dtf));// 2021-01-29 十位转八位 ==> 20210129
dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
System.out.println(l.format(dtf));// 2021-01-29 ==> 2021年01月29日
dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd");
System.out.println(l.format(dtf));// 2021-01-29 ==> 2021/01/29
六:LocalDate进阶,获取月末、月首、本周一、下周五、每个月的周一
方法 | 说明 |
---|---|
LocalDate with(TemporalAdjuster adjuster) | 使用传递的TemporalAdjuster作为参数来调整此日期时间,并在调整后返回调整后的日期时间的副本 |
LocalDate with(TemporalField field, long newValue) | 用于将LocalDate的指定字段设置为新值并返回新的日期时间的副本。此方法可用于更改任何受支持的字段,例如年,月或day-of-month。如果由于不支持该字段或其他原因而无法设置新值,则会引发异常。 |
LocalDate withMonth(int month) | 修改LocalDate变量的月份,如LocalDate.parse(“2021-10-30”).withMonth(3)则为2021-03-30 month:从1到12 |
LocalDate withDayOfMonth(int dayOfMonth) | 修改LocalDate变量的日,如LocalDate.parse(“2021-10-30”).withDayOfMonth(3)则为2021-10-03 dayOfMonth:从1到28-31 |
LocalDate withDayOfYear(int dayOfYear) | 返回当年第几天的日期,如当年第300天是几月几号,dayOfYear从1到365-366 |
LocalDate withYear(int year) | 修改LocalDate变量的年份,如LocalDate.parse(“2021-10-30”).withYear(2000)则为2000-10-30 year:从MIN_YEAR到MAX_YEAR |
1、LocalDate with(TemporalAdjuster adjuster)
- 该方法用于使用传递的TemporalAdjuster作为参数来调整此日期时间,并在调整后返回调整后的日期时间的副本。
- 使用指定的调整器策略对象进行调整。
- 该LocalDate实例是不可变的,不受此方法调用的影响。
参数:该方法接受调节器作为要使用的调节器的参数。
返回值:该方法将基于此方法返回LocalDate并进行调整。
异常:此方法引发以下异常:
- DateTimeException–如果无法进行调整。
- ArithmeticException–如果发生数字溢出。
TemporalAdjuster:时间调节器
有的时候,你需要进行一些更加灵活复杂的操作,比如,将日期调整到下个周日、下个工作日,或者是本月的最后一天。
这时,就需要时间调节器 TemporalAdjuster,可以更加灵活地处理日期。
TemporalAdjusters 工具提供了一些通用的功能,并且你还可以新增你自己的功能。
方法 | 说明 |
---|---|
static TemporalAdjuster firstDayOfMonth() | 当前月的第一天 |
static TemporalAdjuster firstDayOfNextMonth() | 下一个月的第一天 |
static TemporalAdjuster firstDayOfNextYear() | 下一年的第一天 |
static TemporalAdjuster firstDayOfYear() | 当年的第一天 |
static TemporalAdjuster lastDayOfYear() | 当年的最后一天 |
static TemporalAdjuster lastDayOfMonth() | 当月的最后一天 |
static TemporalAdjuster firstInMonth(DayOfWeek dayOfWeek) | 某月的第一个星期几 |
static TemporalAdjuster lastInMonth(DayOfWeek dayOfWeek) | 某月的最后一个星期几 |
static TemporalAdjuster dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) | 某月的第几个星期几,例如,三月中第二个星期二 |
static TemporalAdjuster next(DayOfWeek dayOfWeek) | (往后不包括当天)下一个星期几是几月几号。若当前为周三,那么next(DayOfWeek.WEDNESDAY)指下一个周三即下周三;next(DayOfWeek.SUNDAY) 指下一个周日即本周日(此时并不是下周日) |
static TemporalAdjuster nextOrSame(DayOfWeek dayOfWeek) | (往后包括当天)最近星期几的日期。如最近星期五的日期,如果今天是星期五,则返回今天日期,如果今天不是星期五,则返回下周五的日期 |
static TemporalAdjuster previous(DayOfWeek dayOfWeek) | (往前不包括当天)上一个星期几是几月几号。若当前为周三,那么previous(DayOfWeek.WEDNESDAY)指上一个周三即上周三;previous(DayOfWeek.TUESDAY) 指上一个周二即昨天(此时并不是上周二) |
static TemporalAdjuster previousOrSame(DayOfWeek dayOfWeek) | (往前包括当天)最近星期几的日期。如最近星期五的日期,如果今天是星期五,则返回今天日期,如果今天不是星期五,则返回上周五的日期 |
LocalDate now = LocalDate.now();
System.out.println("当前时间:"+now); //2021-11-30
//获取当月第一天
System.out.println("当月第一天:"+now.with(TemporalAdjusters.firstDayOfMonth()));// 2021-11-01
//获取本月第2天:
System.out.println("本月第2天:"+now.withDayOfMonth(2)); //2021-11-02
//获取下月第一天
System.out.println("下月第一天:"+now.with(TemporalAdjusters.firstDayOfNextMonth())); //2021-12-01
//获取明年第一天
System.out.println("明年第一天:"+now.with(TemporalAdjusters.firstDayOfNextYear())); //2022-01-01
//获取本年第一天
System.out.println("本年第一天:"+now.with(TemporalAdjusters.firstDayOfYear()));//2021-01-01
//获取当月最后一天,再也不用计算是28,29,30还是31:
System.out.println("当月最后一天:"+now.with(TemporalAdjusters.lastDayOfMonth())); //2021-11-30
//获取本年最后一天
System.out.println("本年最后一天:"+now.with(TemporalAdjusters.lastDayOfYear())); //2021-12-31
//获取当月的第一个星期一
System.out.println("当月的第一个星期一:"+now.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))); //2021-11-01
//获取当月的最后一个星期一
System.out.println("当月的最后一个星期一:"+now.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY))); //2021-11-29
//获取当月第三周星期五
System.out.println("当月第三周星期五:"+now.with(TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.FRIDAY))); //2021-11-19
//获取本周一
System.out.println("本周一:"+now.with(DayOfWeek.MONDAY)); //2021-11-29
//获取上周二
System.out.println("上周二:"+now.minusWeeks(1).with(ChronoField.DAY_OF_WEEK, 2)); //2021-11-23
//(往前不包括当天)获取当前日期的上一个周一 如果今天是周一,则返回上周一
System.out.println("上一个周一(不包括当天):"+now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY))); //2021-11-29
//(往前包括当天)最近星期五的日期 如果今天是星期五,则返回今天日期
System.out.println("上一个周一(包括当天):"+now.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY))); //2021-11-26
//获取下周二
System.out.println("下周二:"+now.plusWeeks(1).with(ChronoField.DAY_OF_WEEK, 2)); //2021-12-07
//(往后不包括当天)获取当前日期的下一个周日 如果今天是周日,则返回下周日的时间 如果今天是星期一,则返回本周日的时间
System.out.println("下一个周日(不包括当天):"+now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY))); //2021-12-05
//(往后包括当天)最近星期五的日期 如果今天是星期五,则返回今天日期
System.out.println("下一个周日(包括当天):"+now.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))); //2021-12-03
七:LocalDateTime与Date的互转
public static LocalDateTime dateToLocalDateTime(Date date) {
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
return instant.atZone(zoneId).toLocalDateTime();
}
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(zoneId);
return Date.from(zdt.toInstant());
}
参考:
LocalDate官方apihttps://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
相关文章