紀錄下 Java 的各種日期時間操作
使用 JDK 11
package test;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
public class DateTimeFormatterTest {
public static void main(String[] args) {
String timeStr = "2023-01-01T00:00:00+00:00";
//使用 DateTimeFormatter
DateTimeFormatter dtf_utc0 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxxx")
.withZone(ZoneId.of("+0000"));
//上例可以簡單寫成 DateTimeFormatter dtf = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
OffsetDateTime offsetDateTime = OffsetDateTime.parse(timeStr, dtf_utc0);
//轉換成 Date
Date date = Date.from(offsetDateTime.toInstant());
//轉換成 Calendar
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
//將 Calendar 轉成 Date,再從 Date 轉成 OffsetDateTime
//atOffset(Offset) 只是用來把 Date 轉成 OffsetDateTime,
//Offset 設多少不重要,因為都可以再用 DateTimeFormatter.format() 將其 format 成其他時區的日期文字
OffsetDateTime offsetDateTime2 = calendar.getTime() // 將 Calendar 轉成 Date
.toInstant()
.atOffset(ZoneOffset.of("+0800"));
//用不同時區和 format 印出日期,可以注意 xxx 和 xx 的不同,xxx會印出冒號而xx不會
DateTimeFormatter dtf_utc3 = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssxx")
.withZone(ZoneId.of("+0300"));
System.out.println(dtf_utc3.format(offsetDateTime2)); //2023-01-01T03:00:00+0300
////////////////////////// - LocalDate, LocalTime 等串接練習 - //////////////////
//只有日期沒有時間的 DateTimeFormatter
DateTimeFormatter dtf_utc0_dateOnly = DateTimeFormatter.ofPattern("yyyy-MM-dd")
.withZone(ZoneId.of("+0000"));
//含有有日期及時間的 DateTimeFormatter
DateTimeFormatter dtf_losAngeles_withTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.of("America/Los_Angeles"));
//只有日期不含時間、時區的 LocalDate
LocalDate localDate = LocalDate.parse("2024-01-01", dtf_utc0_dateOnly);
System.out.println(localDate); //2024-01-01
//只有時間不含日期、時區的 LocalTime
LocalTime localTime = LocalTime.of(0, 0, 0);
System.out.println(localTime); //00:00
//LocalDateTime 含有日期和時間,但不含時區,可以用 LocalDate 加 LocalTime 組合而成
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
System.out.println(localDateTime); //2024-01-01T00:00
//OffsetDateTime 含有日期、時間和時區,可以用 LocalDateTime 加 ZoneOffset 組合而成
OffsetDateTime offsetDateTime1 = OffsetDateTime.of(localDateTime, ZoneOffset.of("+0000"));
System.out.println(dtf_losAngeles_withTime.format(offsetDateTime1)); //2023-12-31 16:00:00
//OffsetDateTime 也提供多種不同的建立 Method,
//例如其中的一個 OffsetDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset)
//它可以用以1來表示1月 (而不是用0來表示1月),如下例:
OffsetDateTime offsetDateTime_uct0 = OffsetDateTime.of(2024, 6, 6, 20, 0, 0, 0, ZoneOffset.of("+0000"));
System.out.println(offsetDateTime_uct0); //2024-06-06T20:00Z
//得到當日是星期幾,可能會依不同時區而不同
System.out.println(offsetDateTime_uct0.getDayOfWeek()); //THURSDAY
//可以把日期、時間提出來換上不同時區建立新的 OffsetDateTime,此時其 Instant 代表的毫秒數可能會改變
System.out.println(OffsetDateTime.of(offsetDateTime_uct0.toLocalDateTime(), ZoneOffset.of("+0800"))); //2024-06-06T20:00+08:00
//可以用 OffsetDateTime.withOffsetSameInstant(ZoneOffset)在Instant代表毫秒數不變的情況下修改時區
OffsetDateTime offsetDateTime_uct8 = offsetDateTime_uct0.withOffsetSameInstant(ZoneOffset.of("+0800"));
System.out.println(offsetDateTime_uct8); //2024-06-07T04:00+08:00
//可以看到因為時區不同而顯示不同的星期
System.out.println(offsetDateTime_uct8.getDayOfWeek()); //FRIDAY
//////////////////////////- TemporalAdjusters 練習 - //////////////////
//配合 OffsetDateTime.with() 和 TemporalAdjusters 可以得到特定條件的修改時間,
//例如此例使用 TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY)
//可以得到往前算的最近一次星期五(包含今天)
OffsetDateTime lastFirdayIncludeToday_utc0 = offsetDateTime_uct0.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY));
System.out.println(lastFirdayIncludeToday_utc0); //2024-05-31T20:00Z
OffsetDateTime lastFirdayIncludeToday_utc8 = offsetDateTime_uct8.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY));
System.out.println(lastFirdayIncludeToday_utc8); //2024-06-07T04:00+08:00
}
}
參考資料: