alamide的笔记库「 87篇笔记 」「 小破站已建 0 天啦 🐶 」


Java 基础 DateTime

2023-04-16, by alamide

Java 基础语法 日期和时间,学习内容来自 《Java 实战(第二版)》

Java 基础之日期时间相关,Java1.0 使用的是 java.util.Date ,这个工具类有一些缺陷,无法表示日期,且只能以毫秒精度表示时间, 更糟糕的是它的易用性,由于某些原因未知的设计决策,这个类的易用性被深深地损害了,比如:年份的起始选择是1900年,月份的起始从0开始。 这个类会让人很困惑,Date 是表示日期的意思,是不连续的,但是这里却用来表示时间。

Java1.1 中,Date 类中很多方法被废弃了,取而代之的是 java.util.Calendar ,但是也有缺陷,很困惑到底使用哪一个。

Java8 之后提供了新的时间和日期 API,LocalDate、LocalTime、LocalDateTime、Instant、Duration、Period。

1.时间与日期

1.1 LocalDate

final LocalDate localDate = LocalDate.of(2023, 4, 16);
final int dayOfWeek = localDate.getDayOfWeek().getValue();
final int dayOfYear = localDate.getDayOfYear();
final int dayOfMonth = localDate.getDayOfMonth();
final int monthValue = localDate.getMonthValue();
final int lengthOfMonth = localDate.lengthOfMonth();//获取这一月天数
final int lengthOfYear = localDate.lengthOfYear();//获取这一年天数

1.2 LocalTime

LocalTime localTime = LocalTime.of(10, 0, 0);

1.3 LocalDateTime

LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
final LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
final LocalDateTime localDateTime1 = LocalDateTime.of(2023, Month.APRIL, 16, 11, 15);
final LocalDateTime localDateTime2 = localDate.atTime(11, 15, 15);
final LocalDateTime localDateTime3 = localDate.atTime(localTime);
final LocalDateTime localDateTime4 = localTime.atDate(localDate);

1.4 Instant

final Instant now = Instant.now();
final Instant instant1 = Instant.ofEpochSecond(3);
final Instant instant2 = Instant.ofEpochSecond(3, 0);
final Instant instant3 = Instant.ofEpochSecond(2, 1_000_000_000);
final Instant instant4 = Instant.ofEpochSecond(4, -1_000_000_000);

2.时间和日期间隔

2.1 Duration

Duration类主要用于以秒和纳秒衡量时间的长短,所以不能仅向between方法传递一个LocalDate对象做参数

final Instant instant1 = Instant.now();
final Instant instant2 = Instant.now();
final Duration duration = Duration.between(instant1, instant2);
final long nanos = duration.get(ChronoUnit.NANOS);

final LocalDateTime localDateTime1 = LocalDateTime.of(2023, 4, 15, 11,11,11);
final LocalDateTime localDateTime2 = LocalDateTime.of(2023, 4, 16,11,11);
final Duration between = Duration.between(localDateTime1, localDateTime2);
final long seconds = between.get(ChronoUnit.SECONDS);

2.2 Period

以年、月或者日的方式对多个时间单位建模,那么可以使用Period类

final LocalDate localDate1 = LocalDate.of(2023, 3, 3);
final LocalDate localDate2 = LocalDate.of(2024, 4, 10);
final Period period = Period.between(localDate1, localDate2);

3.操作、解析和格式化日期

3.1 修改属性

修改属性会创建一个新的对象,并不会修改原来的对象

final LocalDate localDate = startDate.withYear(2012);
final LocalDate localDate1 = localDate.with(ChronoField.MONTH_OF_YEAR, 2);

3.2 TemporalAdjuster

//下一个周日
final LocalDate nextSunDay = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
//年末
final LocalDate lastDayOfYear = LocalDate.now().with(TemporalAdjusters.lastDayOfYear());

//下一个工作日
final LocalDate nextWorkDate = LocalDate.now().with(temporal -> {
    final DayOfWeek dayOfWeek = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
    int dayAdd = 1;
    if (dayOfWeek == DayOfWeek.FRIDAY) {
        dayAdd = 3;
    } else if (dayOfWeek == DayOfWeek.SATURDAY) {
        dayAdd = 2;
    }
    return temporal.plus(dayAdd, ChronoUnit.DAYS);
});

3.3 格式化

//20230416
final String format1 = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
//2023-04-16
final String format2 = LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
//2023-04-16
final LocalDate parseDate = LocalDate.parse("20230416", DateTimeFormatter.BASIC_ISO_DATE);

final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
//16/04/2023
final String format3 = LocalDate.now().format(dateTimeFormatter);

final DateTimeFormatter dateTimeFormatter1 = new DateTimeFormatterBuilder()
        .appendText(ChronoField.MONTH_OF_YEAR)
        .appendLiteral("%")
        .appendText(ChronoField.DAY_OF_MONTH)
        .appendLiteral("*")
        .appendText(ChronoField.YEAR)
        .parseCaseInsensitive()
        .toFormatter(Locale.CHINESE);
//四月%16*2023
final String format4 = LocalDate.now().format(dateTimeFormatter1);

3.4 时区

final Instant instant1 = Instant.now();
System.out.println(instant1);
final ZonedDateTime zonedDateTime = instant1.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);

final Instant instant = LocalDateTime.now().toInstant(ZoneOffset.UTC);
final LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.now(), ZoneId.of("America/Anchorage"));
final LocalDateTime localDateTime1 = LocalDateTime.ofInstant(Instant.now(), ZoneId.of("UTC+7"));
final LocalDateTime localDateTime2 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());

4.Snippets

计算预产期及孕期信息

final LocalDate startDate = LocalDate.of(2023, 1, 16);
final LocalDate goalDate = startDate.plusDays(280);
final LocalDate now = LocalDate.now();
final long weeks = ChronoUnit.WEEKS.between(startDate, now);
final long days = ChronoUnit.DAYS.between(startDate.plusWeeks(weeks), now);

log.info("预产期为:{}, 当前为:孕 {} 周 + {} 天", goalDate, weeks, days);

新年倒计时

final LocalDateTime goalDate = LocalDate.now().plusYears(1).withDayOfYear(1).atStartOfDay();
        
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        final long gapSeconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), goalDate);
        final long days = Duration.ofSeconds(gapSeconds).toDaysPart();
        final long hours = Duration.ofSeconds(gapSeconds).toHoursPart();
        final long minutes = Duration.ofSeconds(gapSeconds).toMinutesPart();
        final long seconds = Duration.ofSeconds(gapSeconds).toSecondsPart();

        log.info("距离新的一年还剩:{} 天 {} 时 {} 分 {} 秒", String.format("%03d", days), String.format("%02d", hours), String.format("%02d", minutes), String.format("%02d", seconds));
    }
}, 0, 1000);

System.in.read();
Tags: Java - DateTime
~ belongs to alamide@163.com