日期和時間API - 讀《Java 8實戰》

日期與時間

LocalDate

建立一個LocalDate對象並讀取其值java

// 根據年月日建立日期
LocalDate date1 = LocalDate.of(2014, 3, 18);

// 讀取
System.out.println(date1.getYear()); // 2014
System.out.println(date1.getMonth()); // MARCH
System.out.println(date1.getMonth().getValue()); // 3
System.out.println(date1.getDayOfMonth()); // 18
System.out.println(date1.lengthOfMonth()); // 31
System.out.println(date1.isLeapYear()); // false

// 當前日期
LocalDate now = LocalDate.now();
System.out.println(now); // 2018-08-14

// 從日期對象中獲取年月日
System.out.println(now.get(ChronoField.YEAR)); // 2018
System.out.println(now.get(ChronoField.MONTH_OF_YEAR)); // 8
System.out.println(now.get(ChronoField.DAY_OF_MONTH)); // 14

LocalTime

建立LocalTime並讀取值ide

// 根據時分秒建立時間
LocalTime time1 = LocalTime.of(13, 45, 20);
System.out.println(time1.getHour()); // 13
System.out.println(time1.getMinute()); // 45
System.out.println(time1.getSecond()); // 20

// 經過日期或時間字符串建立日期或時間
LocalDate date2 = LocalDate.parse("2014-03-18");
LocalTime time2 = LocalTime.parse("13:45:20");

LocalDateTime

直接建立LocalDateTime對象或經過合併日期和時間的方式建立code

// 直接建立日期時間
LocalDateTime lt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);

// 經過日期和時間建立
LocalDate date1 = LocalDate.of(2014, 3, 18);
LocalTime time1 = LocalTime.of(13, 45, 20);
LocalDateTime lt2 = LocalDateTime.of(date1, time1);
LocalDateTime lt3 = date1.atTime(13, 45, 20);
LocalDateTime lt4 = date1.atTime(time1);
LocalDateTime lt5 = time1.atDate(date1);

// 從日期時間中提取日期和時間
LocalDate date2 = lt1.toLocalDate();
LocalTime time2 = lt1.toLocalTime();

Instant

機器的日期和時間格式orm

// 獲取當前時刻時間戳
System.out.println(Instant.now().toEpochMilli()); // 1534255959679

時間段

Duration & Period

Druation時間間隔單位是時分秒,Period時間間隔單位年月日對象

建立Duration和Period對象接口

LocalDate date1 = LocalDate.parse("2018-08-12");
LocalDate date2 = LocalDate.parse("2018-08-11");
LocalTime time1 = LocalTime.parse("12:45:20");
LocalTime time2 = LocalTime.parse("12:45:21");
Instant instant1 = Instant.ofEpochSecond(22);
Instant instant2 = Instant.ofEpochSecond(11);

// 時間間隔是時間秒
Duration d2 = Duration.between(time1, time2); // time2 - time1
Duration d3 = Duration.between(instant1, instant2); // instant2 - instant1
Duration d4 = Duration.ofMinutes(3); // 建立一個3分鐘的時間段
System.out.println(d2.getSeconds()); // 1
System.out.println(d4.getSeconds()); // 180

// 時間間隔是年月日
Period p1 = Period.between(date1, date2); // date2 - date1
Period p2 = Period.ofDays(10);
System.out.println(p1.getDays()); // -1
System.out.println(p2.getDays()); // 10

操縱、解析和格式化日期

修改LocalDate對象屬性字符串

LocalDate date1 = LocalDate.of(2014, 3, 18);

// 以比較直觀的方式修改
LocalDate date1 = date1.withYear(2011); // 修改年
LocalDate date1 = date1.withMonth(11); // 修改月
LocalDate date1 = date1.withDayOfMonth(25); // 修改日

// 以相對方式修改
date1.minusYears(1); // 減1年
date1.plusYears(2); // 加2年
date1.plus(3, ChronoUnit.MONTHS); // 加3月
date1.plus(22, ChronoUnit.DAYS); // 加22天

TemporalAdjuster

LocalDate date1 = LocalDate.of(2014, 3, 18);

// 當前日期以後包括當前日期的第一個星期日
System.out.println(date1.with(nextOrSame(DayOfWeek.SUNDAY))); // 2014-03-23

// 當月第一個星期日
System.out.println(date1.with(firstInMonth(DayOfWeek.SUNDAY))); // 2014-03-02
// 當月最後一個星期日
System.out.println(date1.with(lastInMonth(DayOfWeek.SUNDAY))); // 2014-03-30
// 當月第一天
System.out.println(date1.with(firstDayOfMonth())); // 2014-03-01
// 當月最後一天
System.out.println(date1.with(lastDayOfMonth())); // 2014-03-31

// 當年第一天
System.out.println(date1.with(firstDayOfYear())); // 2014-01-01
// 明年第一天
System.out.println(date1.with(firstDayOfNextYear())); // 2015-01-01

定製一個TemopralAdjuster

求下一個工做日get

當前日期若是是週日到週四,日期向後移1天 當前日期若是是週五或週六,日期移到下週一it

方案一:實現一個TemporalAdjuster類io

public class NextWorkingDay implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal temporal) {
        // 當前日期是周幾
        DayOfWeek dow =
                DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
        // 判斷要向後移幾天
        int dayToAdd = 1;
        if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
        else if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
        return temporal.plus(dayToAdd, ChronoUnit.DAYS);
    }
}

方案二:直接使用Lambda使用

LocalDate nextWorkingDate = LocalDate.now()
    .with(temporal -> {
        // 當前日期是周幾
        DayOfWeek dow =
            DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
        // 判斷要向後移幾天
        int dayToAdd = 1;
        if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
        else if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
        return temporal.plus(dayToAdd, ChronoUnit.DAYS);
    });

方案三:使用Lambda實現一個TemporalAdjuster

TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(
    temporal -> {
        // 當前日期是周幾
        DayOfWeek dow =
            DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
        // 判斷要向後移幾天
        int dayToAdd = 1;
        if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
        else if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
        return temporal.plus(dayToAdd, ChronoUnit.DAYS);
    }
);

輸出及解析日期時間對象

LocalDate date1 = LocalDate.of(2014, 3, 18);
System.out.println(date1.format(DateTimeFormatter.BASIC_ISO_DATE)); // 20140318
System.out.println(date1.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2014-03-18

LocalDate date2 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date3 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);

// 按照某個模式建立DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
System.out.println(date1.format(formatter)); // 2014/03/18
LocalDate date4 = LocalDate.parse("2018/08/14", formatter);

// 建立一個本地化的DateTimeFormatter
DateTimeFormatter italianFormatter =
    DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN);
System.out.println(date1.format(italianFormatter)); // 18. marzo 2014
LocalDate date5 = LocalDate.parse("18. marzo 2014", italianFormatter);

時區與曆法

ZoneId

// 打印全部時區
ZoneId.getAvailableZoneIds().stream()
	.forEach(System.out::println);

// 建立一個時區,格式爲{區域}/{城市}
ZoneId romeZone = ZoneId.of("Europe/Rome");

// 將老的時區對象轉換爲ZoneId
ZoneId newZoneId = TimeZone.getDefault().toZoneId();

//  獲取當前時區
ZoneId defaultZoneId = ZoneId.systemDefault();
System.out.println(defaultZoneId); // Asia/Shanghai

ZonedDateTime

爲時間點添加時區信息

ZoneId romeZone = ZoneId.of("Europe/Rome");

// 爲時間點添加時區信息
LocalDate date1 = LocalDate.now();
ZonedDateTime zdt1 = date1.atStartOfDay(romeZone);

LocalDateTime dateTime1 = LocalDateTime.now();
ZonedDateTime zdt2 = dateTime1.atZone(romeZone);

Instant instant1 = Instant.now();
ZonedDateTime zdt3 = instant1.atZone(romeZone);

// 將LocalDateTime轉換爲Instant
Instant instantFromDateTime = dateTime1.toInstant(ZoneOffset.ofHours(0));
// 將Instant轉換爲LocalDateTime
LocalDateTime dateTimeFromInstant = LocalDateTime.ofInstant(instant1, romeZone);

ZoneOffset

利用和UTC/格林尼治時間的固定誤差計算時區

// 不推薦使用
// 紐約落後於倫敦5小時
ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");
System.out.println(newYorkOffset);
OffsetDateTime dateTimeInNewYork = OffsetDateTime.of(LocalDateTime.now(), newYorkOffset);

別的日曆系統

ISO-8601日曆系統是世界文明日曆系統的事實標準。Java 8 還提供了4種其餘日曆系統,分別是

ThaiBuddhistDate
MinguoDate
JapaneseDate
HijrahDate  // 伊斯蘭教日曆

全部這些類以及LocalDate都實現了ChronoLocalDate接口。

LocalDate date1 = LocalDate.now();
JapaneseDate japaneseDate = JapaneseDate.from(date1);
System.out.println(japaneseDate); // Japanese Heisei 30-08-14

Chronology japaneseChronology = Chronology.ofLocale(Locale.JAPAN);
ChronoLocalDate now = japaneseChronology.dateNow();
System.out.println(now); // 2018-08-14
相關文章
相關標籤/搜索