API Date Time trong Java
- 15-10-2023
- Toanngo92
- 0 Comments
Một điểm yếu lâu đời của các nhà phát triển Java là thiếu sự hỗ trợ mạnh mẽ cho việc sử dụng ngày và thời gian. Các lớp date-time hiện có đã chứng tỏ có nhiều vấn đề, thường buộc các nhà phát triển phải tìm kiếm các thư viện khác để giải quyết yêu cầu của họ.
Tuy nhiên, từ Java 8 trở đi, một API date-time mới đã được giới thiệu, cung cấp giải pháp cho nhiều vấn đề chưa được giải quyết trong API trước đó.
API date-time này được thiết kế để giải quyết các vấn đề sau đây mà thư viện ngày và thời gian trước đây gặp phải:
- Vấn đề an toàn luồng (thread safe) – Vì java.util không an toàn khi sử dụng trong luồng, các nhà phát triển đã gặp khó khăn khi xử lý các vấn đề về đồng thời hóa khi sử dụng dữ liệu liên quan đến ngày. API date-time mới là không thay đổi (immutable) và không có các thủ tục setter. Nó cung cấp tính an toàn luồng.
- Thiết kế kém – Giá trị mặc định của ‘date’ trong các phiên bản trước của Java bắt đầu từ năm 1900; ‘tháng’ bắt đầu từ 1 và ‘ngày’ bắt đầu từ 0, do đó, không có tính đồng nhất. API date-time trước đây thiếu các phương thức gián tiếp được sử dụng cho các hoạt động liên quan đến ngày. API mới có nhiều phương thức tiện ích cho các hoạt động như vậy.
- Vấn đề xử lý múi giờ – Trước đây, các nhà phát triển phải viết rất nhiều mã để xử lý các vấn đề liên quan đến múi giờ. API mới đã được phát triển với thiết kế cụ thể cho miền dữ liệu.
Mục lục
Các lớp của Date-Time API mới
Tất cả các lớp của API mới Date-Time được đặt trong gói java.time. Danh sách lớp thể hiện như sau:
- Clock
- Duration
- Instant
- LocalDate
- LocalDateTime
- LocalTime
- MonthDay
- OffsetDateTime
- Offsettime
- Period
- Year
- YearMonth
- ZonedDateTime
- Zoneld
- ZoneOffset
Lớp CLock
Clock có thể được sử dụng để lấy thời điểm hiện tại, ngày, và giờ bằng cách sử dụng múi giờ. Nhà phát triển có thể sử dụng Clock thay thế cho System.currentTimeMillis() và TimeZone.getDefault().
Ví dụ:
import java.time.Clock;
public class ClockDemo {
public static void main(String[] args) {
// Creates a new Clock instance based on UTC
Clock defaultClock = Clock.systemUTC();
System.out.println("Default Clock: " + defaultClock);
// Creates a clock instance based on system clock zone
Clock defaultClock2 = Clock.systemDefaultZone();
System.out.println("Default Clock 2: " + defaultClock2);
}
}
Một ngày cụ thể có thể được kiểm tra bằng cách so sánh với đối tượng Clock như được hiển thị trong ví dụ phía dưới:
import java.time.*;
public class ClockDemo {
private Clock clock;
public static void main(String[] args) {
// Creates a new Clock instance based on UTC.
Clock defaultClock = Clock.systemUTC();
System.out.println("Clock: " + defaultClock);
// Creates a clock instance based on system clock zone.
Clock defaultClock2 = Clock.systemDefaultZone();
System.out.println("Clock: " + defaultClock2);
ClockDemo objClockDemo = new ClockDemo();
LocalDate eventDate = LocalDate.of(2021, 2, 14);
Clock clock = Clock.systemUTC();
if (eventDate.isBefore(LocalDate.now(clock))) {
System.out.println("Event date is before today");
} else {
System.out.println("Event date is today or in the future");
}
}
}
Tính toán khoảng thời gian
Lớp Duration bao gồm một tập hợp các phương thức có thể được sử dụng để thực hiện các phép tính dựa trên một đối tượng Duration. Ví dụ, phương thức plusSeconds() thêm giây trong một phép tính và phương thức minusSeconds() trừ giây trong một phép tính.
Dưới đây là các phương thức plus hoặc minus:
- plusNanos()
- minusNanos()
- plusMillis()
- minusMillis()
- plusSeconds()
- minusSeconds()
- plusMinutes()
- minusMinutes()
- plusHours()
- minusHours()
- plusDays()
- minusDays()
Tất cả phương thức hoạt động tương tự nhau.
Truy cập vào thời điểm trong một khoảng thời gian
Một đối tượng Duration bao gồm hai thành phần:
- Phần nanogiây (nanoseconds) của thời lượng
- Phần giây (seconds) của thời lượng
Phần nanogiaây ở đây đại diện cho phần của Duration nhỏ hơn một giây. Phần giây đại diện cho phần của Duration lớn hơn một giây.
Bạn có thể sử dụng các phương thức sau để lấy các giá trị này:
- getNano()
- getSeconds()
Duration có thể được chuyển đổi thành các đơn vị thời gian bằng cách sử dụng các phương thức chuyển đổi này:
- toNanos()
- toMillis()
- toMinutes()
- toHours()
- toDays()
Mỗi trong những phương thức này chuyển đổi khoảng thời gian đầy đủ được biểu diễn bởi Duration sang đơn vị thời gian là nanogiây, miligiây, phút, giờ hoặc ngày.
Phương thức getNano() trả về một phần của Duration mà nhỏ hơn một giây. Phương thức toNanos() trả về toàn bộ khoảng thời gian được chuyển đổi sang đơn vị nanogiây.
Đoạn mã dưới thể hiện việc sử dụng phương thức plusDays() và minusDays():
Duration present =... // assume code is written to get apresent duration
Duration samplePlusA=present.plusDays(3);
Duration sampleMinusA=present.minusDays(3);
Tất cả các phương thức tính toán trả về các đối tượng Duration mới biểu diễn thời gian tính từ phép tính. Điều này được thực hiện để giữ cho đối tượng Duration là không thay đổi.
Lớp Instant (java.time.instant)
Lớp Instant là một lớp được bổ sung trong API Date-Time mới. Nó biểu thị một thời điểm cụ thể trong thời gian. Một Instant được định nghĩa là sự cênh lệch so với điểm gốc hoặc điểm khởi đầu, tức là 1/1/1970 – 00:00 – Giờ Trung bình Greenwich (GMT). Nói cách khác, lớp Instant được sử dụng để tạo dấu thời gian (timestamp).
Điều này có thể được sử dụng trong các ứng dụng thực tế như vận chuyển, cập nhật cổ phiếu và nhiều ứng dụng khác.
Tạo một Instant
Một thể hiện của Instant có thể được tạo ra bằng cách sử dụng một trong các phương thức tạo của lớp Instant. Đoạn mã dưới biểu diễn một đối tượng Instant biểu thị thời điểm hiện tại, bằng cách gọi phương thức Instant.now()
Instant sampleNow = Instant.now();
Truy cập thời gian của Instant:
Các trường sau chứa thời gian được biểu thị bởi một đối tượng Instant:
- seconds (giây)
- nanoseconds (nanogiây)
Giá trị seconds trỏ vào số giây kể từ điểm gốc (1/1/1970 00:00 GMT) và giá trị nanoseconds trỏ vào phần của Instant. dưới một giây.
Cả giây và nanoseconds có thể được truy cập thông qua các phương thức sau đây:
- getEpochSecond() (lấy giây Epoch)
- getNano() (lấy nanogiây)
Tính toán với lớp Instant
Có thể thực hiện các tính toán về thời gian và ngày tháng trên lớp Instant bằng cách sử dụng các phương thức cộng hoặc trừ. Ví dụ, các phương thức plusSeconds() và minusSeconds() thêm và trừ đi giây trong tính toán tương ứng, tương tự, tính toán có thể được thực hiện trong nanogiây và mili giây.
Ví dụ:
Instant sampleFeature = sampleNow.plusNanos(4);
/// 4 nanoseconds in future
Instant samplePast = sampleNow.minusNanos(4);
// 4 nanoseconds in past
Lớp LocalDate (java.time.localdate)
Lớp LocalDate trong API Date-Time đề cập đến ngày địa phương, đó là một ngày không có thông tin múi giờ. Một ví dụ về ngày địa phương có thể là ngày sinh nhật hoặc ngày lễ chính thức như Ngày Độc Lập, liên quan đến một ngày cụ thể trong năm và không phải thời gian chính xác của ngày đó (thời điểm bắt đầu ngày).
Lớp LocalDate được đóng gói trong gói java.time. Các đối tượng LocalDate không thay đổi, do đó, tất cả các tính toán trên lớp LocalDate tạo ra một LocalDate mới.
Tạo một LocalDate
Có thể tạo đối tượng LocalDate bằng cách sử dụng một số cách tiếp cận. Cách tiếp cận đầu tiên là lấy một LocalDate tương đương với ngày địa phương của hôm nay. Mã dưới mô tả cách tạo một đối tượng LocalDate bằng cách sử dụng now().
Ví dụ:
import java.time.LocalDateTime; // Import the LocalDateTime class
public class YourClassName {
public static void main(String[] args) {
LocalDateTime sampleLocalDateTimeA = LocalDateTime.now();
System.out.println("Current LocalDateTime: " + sampleLocalDateTimeA);
}
}
Cách tiếp cận khác để có được một LocalDate là tạo nó từ thông tin cụ thể về năm, tháng và ngày.
Ví dụ:
import java.time.LocalDate; // Import the LocalDate class
public class YourClassName {
public static void main(String[] args) {
LocalDate sampleLocalDate = LocalDate.of(2016, 7, 4);
System.out.println("Sample LocalDate: " + sampleLocalDate);
}
}
Phương thức of() của LocalDate tạo ra một thể hiện LocalDate, biểu thị một ngày cụ thể trong một tháng cụ thể của một năm cụ thể, nhưng không bao gồm thông tin về múi giờ.
Thông tin về ngày của một LocalDate có thể được truy cập bằng cách sử dụng các phương thức sau:
Trong API Date-Time, các phương thức sau có thể được sử dụng để truy cập thông tin về ngày của một LocalDate:
- getYear(): Trả về năm của LocalDate.
- getMonth(): Trả về tháng của LocalDate dưới dạng một đối tượng
Month
. - getDayOfMonth(): Trả về ngày trong tháng của LocalDate.
- getDayOfWeek(): Trả về ngày trong tuần của LocalDate dưới dạng một đối tượng
DayOfWeek
. - getDayOfYear(): Trả về ngày trong năm của LocalDate.
Ví dụ sử dụng các phương thức này:
LocalDate date = LocalDate.of(2023, Month.OCTOBER, 2);
int year = date.getYear(); // 2023
Month month = date.getMonth(); // Month.OCTOBER
int dayOfMonth = date.getDayOfMonth(); // 2
DayOfWeek dayOfWeek = date.getDayOfWeek(); // DayOfWeek.MONDAY
int dayOfYear = date.getDayOfYear(); // 275
Điều này cho phép bạn truy cập và sử dụng thông tin về ngày từ một đối tượng LocalDate.
Tính toán với LocalDate
Trong API Date-Time, bạn có thể thực hiện các tính toán liên quan đến LocalDate bằng cách sử dụng các phương thức sau:
- plusDays(int daysToAdd): Thêm một số ngày vào LocalDate.
- minusDays(int daysToSubtract): Trừ đi một số ngày từ LocalDate.
- plusWeeks(long weeksToAdd): Thêm một số tuần vào LocalDate.
- minusWeeks(long weeksToSubtract): Trừ đi một số tuần từ LocalDate.
- plusMonths(long monthsToAdd): Thêm một số tháng vào LocalDate.
- minusMonths(long monthsToSubtract): Trừ đi một số tháng từ LocalDate.
- plusYears(long yearsToAdd): Thêm một số năm vào LocalDate.
- minusYears(long yearsToSubtract): Trừ đi một số năm từ LocalDate.
Dưới đây là một ví dụ sử dụng các phương thức này:
LocalDate date = LocalDate.of(2023, Month.OCTOBER, 2);
LocalDate futureDate = date.plusDays(7); // Thêm 7 ngày
LocalDate pastDate = date.minusMonths(2); // Trừ 2 tháng
Các phương thức này cho phép bạn thực hiện các phép tính về ngày dễ dàng trên đối tượng LocalDate.
Lớp LocalDateTime (java.time.LocalDateTime)
Lớp LocalDateTime trong API Date-Time đại diện cho một ngày và giờ cục bộ mà không có dữ liệu về múi giờ. LocalDateTime có thể được xem như sự kết hợp của các lớp LocalDate và LocalTime trong API Date-Time.
LocalDateTime là bất biến (immutable), vì vậy tất cả các phương thức thực hiện tính toán trên LocalDateTime sẽ tạo ra một đối tượng LocalDateTime mới.
Tạo đối tượng LocalDateTime
Để tạo một đối tượng LocalDateTime, bạn có thể sử dụng một trong các phương thức tạo tĩnh của nó. Dưới đây là một ví dụ sử dụng phương thức now()
để tạo một đối tượng LocalDateTime:
LocalDateTime currentDateTime = LocalDateTime.now();
Điều này sẽ tạo ra một đối tượng LocalDateTime đại diện cho thời điểm hiện tại, bao gồm cả ngày và giờ, nhưng không có thông tin về múi giờ.
Truy cập giá trị thời gian với LocalDateTime
Thông tin ngày tháng của một đối tượng LocalDateTime có thể được truy cập bằng cách sử dụng phương thức getValue (). Ví dụ, phương thức getDayOfYear () hiển thị một ngày cụ thể trong năm và getDayOfWeek () hiển thị một ngày cụ thể trong tuần trong một phép tính.
Dưới đây là các phương thức getValue () tương ứng:
- getYear(): Lấy năm.
- getMonth(): Lấy tháng.
- getDayOfMonth(): Lấy ngày trong tháng.
- getDayOfWeek(): Lấy ngày trong tuần.
- getDayOfYear(): Lấy ngày trong năm.
- getHour(): Lấy giờ.
- getMinute(): Lấy phút.
- getSecond(): Lấy giây.
- getNano(): Lấy nano giây.
Một số phương thức này trả về kết quả dưới dạng giá trị int và một số khác hiển thị một enum. Giá trị int của enum có thể được lấy bằng cách sử dụng phương thức getValue() của enum.
Tính toán Date-Time với LocalDateTime
Một số tính toán liên quan đến ngày và giờ có thể được thực hiện trên đối tượng LocalDateTime bằng cách sử dụng các phương thức plus hoặc minus. Ví dụ, phương thức plusYears () thêm số năm trong một phép tính và phương thức minusYears () trừ số năm trong một phép tính. Dưới đây là các phương thức plus hoặc minus tương ứng:
- plusYears(): Thêm số năm.
- plusMonths(): Thêm số tháng.
- plusDays(): Thêm số ngày.
- plusHours(): Thêm số giờ.
- plusMinutes(): Thêm số phút.
- plusSeconds(): Thêm số giây.
- plusNanos(): Thêm số nanogiaây.
- minusYears(): Trừ số năm.
- minusMonths(): Trừ số tháng.
- minusDays(): Trừ số ngày.
- minusHours(): Trừ số giờ.
- minusMinutes(): Trừ số phút.
- minusSeconds(): Trừ số giây.
- minusNanos(): Trừ số nanogiaây.
Đoạn mã dưới mô tả cách các phương thức tính toán này hoạt động:
import java.time.LocalDateTime;
import java.time.Month;
public class LocalDateTimeExample {
public static void main(String[] args) {
// Tạo một đối tượng LocalDateTime đại diện cho ngày và giờ hiện tại
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("Ngày và giờ hiện tại: " + currentDateTime);
// Thêm 1 năm
LocalDateTime futureDateTime = currentDateTime.plusYears(1);
System.out.println("Ngày và giờ sau khi thêm 1 năm: " + futureDateTime);
// Trừ 3 tháng
LocalDateTime pastDateTime = currentDateTime.minusMonths(3);
System.out.println("Ngày và giờ sau khi trừ 3 tháng: " + pastDateTime);
// Thêm 2 giờ và 30 phút
LocalDateTime newDateTime = currentDateTime.plusHours(2).plusMinutes(30);
System.out.println("Ngày và giờ sau khi thêm 2 giờ và 30 phút: " + newDateTime);
}
}
Lớp LocalTime
Lớp LocalTime trong API Date-Time đại diện cho thời gian chính xác trong một ngày mà không có thông tin về múi giờ. Các đối tượng LocalTime có thể được sử dụng để mô tả các tình huống trong cuộc sống thực, như thời gian bắt đầu học tập hoặc làm việc ở các quốc gia khác nhau. Nó giúp trong việc phân tích sự quan tâm của người dân ở các múi giờ khác nhau đối với thời gian UTC, liên quan đến múi giờ của từng quốc gia cụ thể.
Lớp LocalTime là tuyệt đối (absolute), vì vậy tất cả các tính toán trên đối tượng LocalTime sẽ tạo ra một đối tượng LocalTime mới.
Tạo một đối tượng LocalTime
Một thể hiện LocalTime có thể được tạo ra bằng cách sử dụng một số cách tiếp cận. Cách tiếp cận hàng đầu là tạo một thể hiện LocalTime đại diện cho thời gian hiện tại. Đoạn mã dưới thể hiện phương thức now()
LocalTime timeNow = LocalTime.now();
Một cách tiếp cận khác để tạo một đối tượng LocalTime là tạo nó từ số giờ, phút, giây và nanogiây cụ thể. Ví dụ:
import java.time.LocalTime; // Import the LocalTime class
public class YourClassName {
public static void main(String[] args) {
LocalTime sampleLocTime = LocalTime.of(12, 24, 33, 135); // Hours, Minutes, Seconds, Nanoseconds
System.out.println("Sample LocalTime: " + sampleLocTime);
}
}
Truy cập giá trị thời gian với LocalTime
Các giờ, phút, giây và nanogisecond của một đối tượng LocalTime có thể được đọc bằng cách sử dụng các phương thức sau đây:
- getHour(): Trả về giờ trong ngày dưới dạng int từ 0 đến 23.
- getMinute(): Trả về phút trong giờ dưới dạng int từ 0 đến 59.
- getSecond(): Trả về giây trong phút dưới dạng int từ 0 đến 59.
- getNano(): Trả về nanogisecond trong giây dưới dạng int từ 0 đến 999,999,999.
Dưới đây là một ví dụ về cách bạn có thể sử dụng các phương thức này:
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
LocalTime sampleLocTime = LocalTime.of(12, 24, 33, 135);
int gio = sampleLocTime.getHour();
int phut = sampleLocTime.getMinute();
int giay = sampleLocTime.getSecond();
int nano = sampleLocTime.getNano();
System.out.println("Giờ: " + gio);
System.out.println("Phút: " + phut);
System.out.println("Giây: " + giay);
System.out.println("Nanogisecond: " + nano);
}
}
Mã này sẽ xuất các giá trị của giờ, phút, giây và thành phần nanosecond của đối tượng sampleLocTime.
Tính toán với LocalTime
Lớp LocalTime bao gồm một tập hợp các phương thức có thể thực hiện các phép tính thời gian cục bộ. Ví dụ, phương thức plusMinutes() thêm số phút và minusMinutes() trừ đi số phút từ một giá trị cụ thể trong phép tính. Các phương thức plus hoặc minus này thường được sử dụng trong đối tượng LocalDateTime.
Ví dụ:
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
// Lấy thời gian hiện tại
LocalTime currentTime = LocalTime.now();
System.out.println("Thời gian hiện tại: " + currentTime);
// Thêm 30 phút vào thời gian hiện tại
LocalTime futureTime = currentTime.plusMinutes(30);
System.out.println("Thời gian sau khi thêm 30 phút: " + futureTime);
// Trừ 15 phút khỏi thời gian hiện tại
LocalTime pastTime = currentTime.minusMinutes(15);
System.out.println("Thời gian sau khi trừ 15 phút: " + pastTime);
}
}
Lớp MonthDay
MonthDay là một đối tượng Date-Time không thay đổi (immutable) trong Java, nó biểu thị cả tháng và ngày trong tháng. Ví dụ, bạn có thể sử dụng MonthDay để đại diện cho ngày sinh nhật hoặc ngày nghỉ trong ngân hàng dựa trên tháng và ngày trong tháng. Điều này giúp quản lý và xử lý các sự kiện hoặc ngày quan trọng chỉ cần xem xét tháng và ngày trong tháng mà không quan tâm đến năm.
Ví dụ:
import java.time.*;
public class DateDemo {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
LocalDate dateOfBirth = LocalDate.of(1988, 2, 13);
// Code to retrieve the birthday month and day
MonthDay bday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
// Code to retrieve the current month and day
MonthDay currentMonthDay = MonthDay.from(today);
if (currentMonthDay.equals(bday)) {
System.out.println("**Colorful Joyful Birthday Buddy**");
} else {
System.out.println("Nope, today is not your B'day");
}
}
}
Mã lấy tháng và ngày sinh nhật, dựa trên ngày tháng năm sinh cho trước. Sau đó, nó truy xuất tháng và ngày hiện tại dựa trên ngày tháng năm hiện tại và sau đó so sánh hai giá trị này và hiển thị các thông báo tương ứng.
Lớp OffsetDateTime
Offset DateTime là một biểu thức không thể thay đổi về ngày và giờ với offset. Lớp này lưu trữ tất cả các trường ngày và giờ, với độ chính xác đến nanosecond, cũng như offset (chênh lệch múi giờ) so với UTC/Greenwich. Ví dụ, giá trị ‘Ngày 23 tháng 11 năm 2016 lúc 11:34,21.278965143 +05:00’ có thể được lưu trữ trong một Offset DateTime.
Đoạn mã dưới hiển thị một ví dụ cho biểu thức với vùng múi giờ California là GMT hoặc UTC +07:00 và để lấy một múi giờ tương tự, bạn có thể sử dụng phương thức tĩnh Zoneoffset.of (). Sau khi lấy giá trị offset, bạn có thể tạo một Offset DateTime bằng cách truyền một LocalDateTime và một offset cho nó.
package examoffsetdatetime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class OffsetDateTimeExample {
public static void main(String[] args) {
// Lấy thời gian hiện tại với offset hiện tại từ UTC
OffsetDateTime currentDateTime = OffsetDateTime.now();
System.out.println("Thời gian hiện tại với offset từ UTC: " + currentDateTime);
// Tạo một OffsetDateTime cụ thể với thời gian chỉ định và offset từ UTC
OffsetDateTime specificDateTime = OffsetDateTime.of(2024, 10, 22, 10, 30, 0, 0, ZoneOffset.ofHours(7));
System.out.println("Thời gian cụ thể: " + specificDateTime);
// Lấy thông tin offset của một OffsetDateTime
ZoneOffset offset = specificDateTime.getOffset();
System.out.println("Offset từ UTC: " + offset);
// Chuyển đổi giữa các múi giờ (thay đổi offset)
OffsetDateTime utcDateTime = specificDateTime.withOffsetSameInstant(ZoneOffset.UTC);
System.out.println("Thời gian chuyển đổi sang UTC: " + utcDateTime);
// Thêm hoặc trừ thời gian
OffsetDateTime oneHourLater = currentDateTime.plusHours(1);
System.out.println("Một giờ sau: " + oneHourLater);
}
}
Lớp OffsetTime
OffsetTime là một đối tượng Date-Time không thể thay đổi (immutable) đại diện cho thời gian, thường được quan sát dưới dạng giờ-phút-giây-mili-giây-nano kèm theo offset múi giờ. Lớp này lưu trữ tất cả các trường thời gian với độ chính xác đến nanogisecond, cùng với offset múi giờ. Ví dụ, giá trị ’13:45.30.123456789+02:00′ có thể được lưu trữ trong một đối tượng OffsetTime.
Việc sử dụng các phép toán dựa trên định tính (identity-sensitive) trên OffsetTime có thể dẫn đến kết quả ngẫu nhiên và do đó, không được khuyến nghị. Thay vào đó, bạn nên sử dụng phương thức equals
để so sánh các đối tượng OffsetTime.
Ví dụ:
import java.time.LocalTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
public class OffsetTimeExample {
public static void main(String[] args) {
// Tạo một đối tượng OffsetTime
OffsetTime offsetTime = OffsetTime.of(LocalTime.of(13, 45, 30), ZoneOffset.ofHours(2));
// Hiển thị đối tượng OffsetTime
System.out.println("OffsetTime: " + offsetTime);
// Truy xuất các thành phần thời gian
int hour = offsetTime.getHour();
int minute = offsetTime.getMinute();
int second = offsetTime.getSecond();
ZoneOffset offset = offsetTime.getOffset();
System.out.println("Hour: " + hour);
System.out.println("Minute: " + minute);
System.out.println("Second: " + second);
System.out.println("Offset: " + offset);
}
}
Output:
OffsetTime: 13:45:30+02:00
Hour: 13
Minute: 45
Second: 30
Offset: +02:00
Ví dụ tình huống sử dụng phương thức ofInstant() của lớp OffsetTime:
import java.time.Instant;
import java.time.OffsetTime;
import java.time.ZoneOffset;
public class OffsetTimeOfInstantExample {
public static void main(String[] args) {
// Create an Instant representing a specific point in time
Instant instant = Instant.now();
// Convert the Instant to an OffsetTime with a specific ZoneOffset
OffsetTime offsetTime = OffsetTime.ofInstant(instant, ZoneOffset.ofHours(2));
// Display the OffsetTime
System.out.println("OffsetTime: " + offsetTime);
// Extract and display the components of the OffsetTime
int hour = offsetTime.getHour();
int minute = offsetTime.getMinute();
int second = offsetTime.getSecond();
ZoneOffset offset = offsetTime.getOffset();
System.out.println("Hour: " + hour);
System.out.println("Minute: " + minute);
System.out.println("Second: " + second);
System.out.println("Offset: " + offset);
}
}
Lớp Period (java.time.Period)
Lớp Period (java.time.Period) đại diện cho một khoảng thời gian dưới dạng số ngày, tháng và năm.
Duration và Period tương đối tương tự; tuy nhiên, sự khác biệt giữa hai loại này có thể thấy trong cách tiếp cận của chúng đối với Daylight Savings Time (DST) khi chúng được thêm vào ZonedDateTime. Duration sẽ thêm một số giây cụ thể, điều này có nghĩa rằng duration của một ngày là chính xác 24 giờ. Trong khi đó, Period sẽ thêm một ngày lý thuyết và không phải là 24 giờ thực tế, cố gắng duy trì thời gian cục bộ.
Hãy xem xét một ví dụ để hiểu điều này. Thêm một khoảng thời gian là một ngày và một duration là một ngày vào 22:00 vào buổi tối trước một khoảng thời gian DST. Period tính toán một ngày lý thuyết và kết quả là ZonedDateTime lúc 22:00 vào ngày mai. Trong khi đó, Duration thêm chính xác 24 giờ và kết quả là ZonedDateTime vào 23:00 vào ngày mai (khoảng thời gian DST khoảng 60 phút).
Để hiểu sự khác biệt giữa lớp Duration
và Period
, hãy xem xét một ví dụ cụ thể:
Giả sử bạn có một ZonedDateTime đại diện cho thời điểm 22:00 vào ngày 1 tháng 3 năm 2023, và bạn muốn thêm một khoảng thời gian là 1 ngày và 1 tháng vào thời điểm này bằng cả Duration và Period.
Sử dụng Duration:
import java.time.*;
public class DurationExample {
public static void main(String[] args) {
ZonedDateTime dateTime = ZonedDateTime.of(2023, 3, 1, 22, 0, 0, 0, ZoneId.of("UTC"));
Duration duration = Duration.ofDays(1).plus(Duration.ofDays(30));
ZonedDateTime result = dateTime.plus(duration);
System.out.println(result);
}
}
Sử dụng Period:
import java.time.*;
public class PeriodExample {
public static void main(String[] args) {
ZonedDateTime dateTime = ZonedDateTime.of(2023, 3, 1, 22, 0, 0, 0, ZoneId.of("UTC"));
Period period = Period.ofDays(1).plus(Period.ofMonths(1));
ZonedDateTime result = dateTime.plus(period);
System.out.println(result);
}
}
Sự khác biệt ở đây là Duration thêm chính xác 1 ngày và 1 tháng vào thời gian, trong khi Period thêm một ngày lý thuyết và một tháng lý thuyết. Do đó, kết quả sẽ khác nhau:
- Với Duration, bạn sẽ có ZonedDateTime là 23:00 vào ngày tiếp theo.
- Với Period, bạn sẽ có ZonedDateTime là 22:00 cùng ngày, nhưng trong trường hợp này, nó là một ngày và một tháng sau khi đã tính đến các điều chỉnh DST.
Xét ví dụ về cách sử dụng phương thức `between()` và `ofDays()` của lớp `Period` để tính thời gian giữa hai ngày:
import java.time.*;
import java.time.temporal.*;
public class PeriodExample {
public static void main(String[] args) {
LocalDate startDate = LocalDate.of(2023, 3, 1);
LocalDate endDate = LocalDate.of(2023, 5, 15);
// Sử dụng between() để tính khoảng thời gian giữa hai ngày
Period periodBetween = Period.between(startDate, endDate);
System.out.println("Khoảng thời gian giữa hai ngày: " + periodBetween);
// Sử dụng ofDays() để tạo một khoảng thời gian với số ngày cụ thể
Period periodOfDays = Period.ofDays(30);
System.out.println("Khoảng thời gian 30 ngày: " + periodOfDays);
}
}
Output:
Khoảng thời gian giữa hai ngày: P2M14D (2 tháng và 14 ngày)
Khoảng thời gian 30 ngày: P30D (30 ngày)
Ở ví dụ trên, chúng ta sử dụng Period.between(startDate, endDate) để tính khoảng thời gian giữa hai ngày startDate và endDate. Sau đó, chúng ta sử dụng Period.ofDays(30) để tạo một khoảng thời gian 30 ngày.
Lớp Year (java.time.Year)
Đối tượng Year (java.time.Year) là một đối tượng Date-Time không thay đổi đại diện cho một năm.
Lớp này không lưu trữ hoặc đại diện cho một tháng cụ thể, ngày, thời gian hoặc múi giờ.
import java.time.Year;
public class SampleYear {
public static void main(String[] args) {
System.out.println("The Present Year: " + Year.now());
int yearToCheck1 = 2022;
boolean isLeapYear1 = Year.of(yearToCheck1).isLeap();
System.out.println("Is the year " + yearToCheck1 + " a leap year? " + isLeapYear1);
int yearToCheck2 = 2024;
boolean isLeapYear2 = Year.of(yearToCheck2).isLeap();
System.out.println("Is the year " + yearToCheck2 + " a leap year? " + isLeapYear2);
}
}
Output:
The Present Year(): 2021
The year 2022 is a Leap year: false
The year 2024 is a Leap year: true
Lớp YearMonth (java.time.YearMonth)
YearMonth (java.time.YearMonth) là một đối tượng Date-Time ổn định đại diện cho sự kết hợp của năm và tháng. Bất kỳ trường nào có thể có từ năm và tháng, chẳng hạn như quý của năm, có thể được thu được. Lớp này không lưu trữ hoặc đại diện cho một ngày, thời gian hoặc múi giờ. Ví dụ, giá trị ‘Tháng 11 năm 2011’ có thể được lưu trữ trong một YearMonth.
YearMonth có thể được sử dụng để đại diện cho các sự kiện như hết hạn thẻ tín dụng, ngày đáo hạn tiền gửi cố định, ngày đáo hạn hợp đồng tương lai chứng khoán, ngày đáo hạn quyền chọn mua chứng khoán hoặc để xác định xem năm đó có phải là năm nhuận hay không.
Ví dụ:
import java.time.YearMonth;
public class LeapYearExample {
public static void main(String[] args) {
// Tạo một đối tượng YearMonth đại diện cho tháng 2 năm 2024
YearMonth yearMonth = YearMonth.of(2024, 2);
// Kiểm tra xem năm 2024 có phải là năm nhuận không
boolean isLeapYear = yearMonth.isLeapYear();
if (isLeapYear) {
System.out.println("Năm 2024 là năm nhuận.");
} else {
System.out.println("Năm 2024 không phải là năm nhuận.");
}
}
}
ZonedDateTime (java.time.ZonedDateTime)
Lớp ZonedDateTime (java.time.ZonedDateTime) là một lớp không thể thay đổi (immutable) đại diện cho ngày và giờ cùng với thông tin về múi giờ. Lớp này lưu trữ tất cả các trường ngày và giờ và có thể lưu trữ các giá trị nanosecond cùng với thông tin về múi giờ. Ví dụ, giá trị ‘Ngày 15 tháng 11 năm 2011 lúc 21:32.30.34192576 -04:00 ở múi giờ America/New York’ có thể được lưu trữ trong một đối tượng ZonedDateTime. Lớp ZonedDateTime trong API Date-Time đại diện cho ngày và giờ cùng với dữ liệu về múi giờ. Điều này có thể là thời điểm bắt đầu của một sự kiện cụ thể nào đó trên thế giới, chẳng hạn như một hội nghị hoặc sự phóng tên lửa.
Lớp ZonedDateTime là không thể thay đổi, điều này có nghĩa là tất cả các phương thức thực hiện các phép tính trên một đối tượng ZonedDateTime sẽ trả về một đối tượng ZonedDateTime mới.
Bạn có thể chuyển đổi giữa các múi giờ sử dụng tính toán về độ lệch dựa trên quy tắc của múi giờ, việc lấy độ lệch cho một local Date-Time không đơn giản như lấy độ lệch cho một instant.
Dưới đây là ba trường hợp về độ lệch:
- Bình thường (normal): Áp dụng cho tất cả các mùa trong năm; trường hợp bình thường liên quan đến một độ lệch hợp lệ duy nhất cho local Date-Time.
- Khoảng cách dưới (gap): Điều này xảy ra khi đồng hồ nhảy nhanh về phía trước thường do sự thay đổi DST mùa hè từ ‘mùa xuân’ sang ‘mùa thu’. Trường hợp lỗ liên quan đến không có độ lệch hợp lệ trong các giá trị local DateTime.
- Khooảng cách trên (over gap): Điều này xảy ra khi đồng hồ được thiết lập lại tự động do sự thay đổi DST mùa đông từ ‘mùa thu’ sang ‘mùa xuân’. Trường hợp trùng lặp liên quan đến hai độ lệch hợp lệ trong các giá trị local Date-Time.
Tạo đối tượng ZoneDateTime:
Đối tượng ZonedDateTime có thể được tạo ra bằng nhiều cách khác nhau. Cách dễ nhất là gọi phương thức now() của lớp ZonedDateTime. Đoạn mã dưới minh họa cách tạo đối tượng ZonedDateTime bằng cách sử dụng phương thức now().
ZonedDateTime zoDT = ZonedDateTime.now();
Có cách khác để tạo đối tượng ZonedDateTime bằng cách sử dụng phương thức of(). Phương thức này giúp tạo đối tượng ZonedDateTime từ một ngày và thời gian cụ thể. Đoạn mã dưới minh họa cách tạo đối tượng ZonedDateTime bằng cách sử dụng phương thức of().
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class ZonedDateTimeExample {
public static void main(String[] args) {
// Tạo một LocalDateTime cho ngày và thời gian cụ thể
LocalDateTime localDateTime = LocalDateTime.of(2023, 10, 15, 14, 30);
// Chọn một múi giờ cụ thể, ví dụ: múi giờ New York
ZoneId zoneId = ZoneId.of("America/New_York");
// Sử dụng phương thức 'of()' để tạo ZonedDateTime từ LocalDateTime và ZoneId
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
System.out.println("ZonedDateTime: " + zonedDateTime);
}
}
Truy cập giá trị Date và Time của đối tượng ZonedDateTime
Thông tin về ngày và giờ dựa trên múi giờ của đối tượng ZonedDateTime
có thể được truy cập bằng cách sử dụng các phương thức như getDayOfMonth()
để hiển thị ngày cụ thể trong tháng và getDayOfWeek()
để hiển thị ngày cụ thể trong tuần trong tính toán. Ví dụ:
import java.time.ZonedDateTime;
public class ZonedDateTimeExample {
public static void main(String[] args) {
// Tạo một đối tượng ZonedDateTime cho thời điểm hiện tại
ZonedDateTime zonedDateTime = ZonedDateTime.now();
// Truy cập thông tin về ngày và giờ trong múi giờ của đối tượng ZonedDateTime
int dayOfMonth = zonedDateTime.getDayOfMonth();
String dayOfWeek = zonedDateTime.getDayOfWeek().toString();
System.out.println("Ngày trong tháng: " + dayOfMonth);
System.out.println("Ngày trong tuần: " + dayOfWeek);
}
}
Trong ví dụ này, chúng ta tạo một đối tượng ZonedDateTime cho thời điểm hiện tại và sau đó sử dụng các phương thức getDayOfMonth() và getDayOfWeek() để truy cập thông tin về ngày và ngày trong tuần của thời điểm đó trong múi giờ của nó.
Đoạn mã dưới mô tả cách truy cập năm của ZonedDateTime:
int sampleYear = zonedDateTime.now().getYear();
int sampleMonth = zonedDateTime.now().getMonth().getValue();
Tính toán Date và Time
Đối tượng ZonedDateTime chứa một tập hợp các phương thức cho phép bạn thực hiện các phép tính về thời gian cục bộ. Ví dụ, phương thức plusHours() thêm giờ và minusHours() trừ giờ từ một giá trị cụ thể trong phép tính. Các phương thức này tương tự như các phương thức plus() và minus() đã được mô tả trước đó trong lớp Date-Time.
Ví dụ:
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class ZonedDateTimeExample {
public static void main(String[] args) {
// Lấy thời gian hiện tại theo múi giờ UTC
ZonedDateTime currentDateTime = ZonedDateTime.now(ZoneId.of("UTC"));
System.out.println("Thời gian hiện tại: " + currentDateTime);
// Thêm 2 giờ vào thời gian hiện tại
ZonedDateTime futureDateTime = currentDateTime.plusHours(2);
System.out.println("Sau khi thêm 2 giờ: " + futureDateTime);
// Trừ 1 giờ từ thời gian hiện tại
ZonedDateTime pastDateTime = currentDateTime.minusHours(1);
System.out.println("Sau khi trừ 1 giờ: " + pastDateTime);
}
}
Ví dụ 2:
import java.time.ZonedDateTime;
import java.time.Period;
public class ZonedDateTimeExample {
public static void main(String[] args) {
// Create an initial ZonedDateTime
ZonedDateTime previousDateTime = ZonedDateTime.now();
// Add a Period of 4 days
ZonedDateTime newZoneDateTime = previousDateTime.plus(Period.ofDays(4));
System.out.println("Previous ZonedDateTime: " + previousDateTime);
System.out.println("New ZonedDateTime after adding 4 days: " + newZoneDateTime);
}
}
Time-zones
Dưới đây là ví dụ về cách sử dụng lớp ZoneId để biểu thị múi giờ, như được thể hiện trong mã phía trên. Đối tượng ZonedDateTime có thể được tạo bằng cách sử dụng phương thức ZoneId.of() như được minh họa như sau:
import java.time.ZoneId;
public class ZoneIdExample {
public static void main(String[] args) {
// Create a ZoneId for UTC
ZoneId sampleZoneId = ZoneId.of("UTC+1");
System.out.println("ZoneId for UTC: " + sampleZoneId);
}
}
Đối số được truyền vào phương thức of()
là ID của múi giờ để tạo một ZoneId. Trong mã trên, ID là ‘UTC+1’, đại diện cho sự chênh lệch so với múi giờ UTC (Greenwich). Bạn có thể xác định chênh lệch UTC cho múi giờ mong muốn và tạo một ID phù hợp bằng cách kết hợp ‘UTC’ với chênh lệch (ví dụ: ‘+1’ hoặc ‘-2’ ở Việt Nam là UTC+7).
Loại ID múi giờ khác bao gồm tên của địa điểm nơi múi giờ đang hoạt động cũng có thể được sử dụng, như được thể hiện trong đoạn mã dưới:
import java.time.ZoneId;
public class ZoneIdExample {
public static void main(String[] args) {
// Create a ZoneId for "America/New_York"
ZoneId sampleZoneIdNY = ZoneId.of("America/New_York");
// Create a ZoneId for "Europe/Paris"
ZoneId sampleZoneIdParis = ZoneId.of("Europe/Paris");
System.out.println("ZoneId for America/New_York: " + sampleZoneIdNY);
System.out.println("ZoneId for Europe/Paris: " + sampleZoneIdParis);
}
}
Ví dụ các phương thức lấy năm, ngày trong năm khi sử dụng ZonedDateTime:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class ZoneDemo {
public static void main(String[] args) {
// Get the current date and time
ZonedDateTime now = ZonedDateTime.now();
System.out.println("Current Date and Time: " + now);
// Parse a specific date and time with a zone
ZonedDateTime sampleZonedDateTime = ZonedDateTime.parse("2021-02-03T10:15:30+08:00[Asia/Singapore]", DateTimeFormatter.ISO_ZONED_DATE_TIME);
// Get the day of the year for the parsed date
int dayOfYear = sampleZonedDateTime.getDayOfYear();
System.out.println("Day of the Year: " + dayOfYear);
// Get the year for the parsed date
int year = sampleZonedDateTime.getYear();
System.out.println("Year: " + year);
}
}
Lớp ZoneId
Một lớp ZoneId được sử dụng để nhận biết các quy tắc được sử dụng để chuyển đổi giữa Instant và LocalDateTime.
Hai kiểu ID khác nhau như sau:
Fixed Offset (lệch múi giờ cố định) – Offset không thay đổi kể từ UTC/Greenwich, cung cấp cùng một offset cho mọi thời điểm cục bộ.
Geographical regions (Các khu vực địa lý) – Bao gồm một bộ quy tắc xác định để tìm offset từ UTC/Greenwich liên quan đến khu vực đó.
Hầu hết các offset tĩnh được đại diện bằng ZoneOffset. Gọi phương thức normalized() trên bất kỳ ZoneOffset nào sẽ đảm bảo rằng một offset ID cố định sẽ được tạo ra dưới dạng một ZoneOffset.
Lớp ZoneOffset
Một offset múi giờ là một lượng thời gian mà múi giờ khác biệt so với Greenwich/UTC. Điều này thường cố định trong hầu hết các trường hợp.
Offset múi giờ khác nhau từ nơi này đến nơi khác trên toàn cầu. Các quy tắc về cách offset thay đổi theo địa điểm và thời gian trong năm được xác định trong lớp ZoneId.
Ví dụ, Berlin chênh lệch hai giờ so với Greenwich/UTC vào mùa xuân và chênh lệch bốn giờ vào mùa thu. Thể hiện (instance) ZoneId cho Berlin sẽ tham chiếu đến hai thể hiện (instance) ZoneOffset – một thể hiện +02:00 cho mùa xuân và một thể hiện +04:00 cho mùa thu.
Ví dụ:
import java.time.ZoneOffset;
public class ZoneOffsetExample {
public static void main(String[] args) {
ZoneOffset springOffset = ZoneOffset.of("+02:00");
ZoneOffset autumnOffset = ZoneOffset.of("+04:00");
System.out.println("Berlin offset in Spring: " + springOffset);
System.out.println("Berlin offset in Autumn: " + autumnOffset);
}
}
Enums
Một kiểu dữ liệu Enumeration (enum) là một kiểu trong Java giúp định rõ số lượng cố định các giá trị được biết đến trong Java. Kiểu này được định nghĩa bằng từ khóa enum. Ví dụ, nó có thể được sử dụng để lưu trữ số ngày trong một tuần hoặc số hành tinh trong hệ Mặt Trời.
Lợi ích của việc sử dụng Enums trong Java:
- Enum là kiểu an toàn và không thể gán với bất kỳ mục nào khác ngoài các hằng số Enum đã định trước cho biến Enum. Gán một giá trị khác ngoài miễn định nghĩa cho một Enum sẽ giây ra lỗi biên dịch.
- Kiểu Enum có không gian tên (namespace) riêng của nó.
- Đặc điểm tốt nhất của Enum là nó có thể được sử dụng trong các câu lệnh switch trong Java tương tự như kiểu dữ liệu nguyên thủy int hoặc char.
- Thêm các hằng số mới bằng cách mở rộng một Enum trong Java dễ dàng và có thể thêm các hằng số mới mà không làm hỏng mã hiện có.
API Date Time trong Java SE 8 trở đi hỗ trợ một số Enum mới và hữu ích. ChronoUnit là một Enum như vậy. Nó định nghĩa một tập hợp tiêu chuẩn các đơn vị khoảng thời gian.
Đoạn mã dưới thể hiện cách sử dụng Enum này. Nó được định nghĩa trong gói java.time.temporal
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class EnumDateCalculation {
public static void main(String[] args) {
EnumDateCalculation java8enum = new EnumDateCalculation();
java8enum.enumChronoUnits();
}
public void enumChronoUnits() {
// To display the current date
LocalDate today = LocalDate.now();
System.out.println("Current date: " + today);
// To display the result after adding 2 weeks to the current date
LocalDate nextWeek = today.plus(2, ChronoUnit.WEEKS);
System.out.println("After 2 weeks: " + nextWeek);
// To display the result after adding 2 months to the current date
LocalDate nextMonth = today.plus(2, ChronoUnit.MONTHS);
System.out.println("After 2 months: " + nextMonth);
// To display the result after adding 2 years to the current date
LocalDate nextYear = today.plus(2, ChronoUnit.YEARS);
System.out.println("After 2 years: " + nextYear);
// To display the result after adding 20 years to the current date
LocalDate nextDecade = today.plus(2, ChronoUnit.DECADES);
System.out.println("Date after twenty years: " + nextDecade);
}
}
Temporal Adjusters (Bộ điều chỉnh thời gian)
TemporalAdjuster là một giao diện tính năng (functional interface) và một công cụ quan trọng để sửa đổi một đối tượng thời gian. Đây là một thực hiện của mẫu thiết kế chiến lược (strategy design pattern) bằng cách sử dụng nó, quá trình điều chỉnh một giá trị được ngoại hóa. Giao diện này có một phương thức là “adjustInto(Temporal)” và có thể được gọi một cách chính xác bằng cách truyền đối tượng Temporal vào. Nó chấp nhận giá trị thời gian đầu vào và trả về giá trị đã được điều chỉnh. Nó cũng có thể được gọi thông qua phương thức “with” của đối tượng thời gian để được điều chỉnh. Giao diện này được định nghĩa trong gói java.time.temporal.
Một TemporalAdjuster có thể được sử dụng để thực hiện các phép toán “toán học” phức tạp về ngày tháng, điều này phổ biến trong các nghiệp vụ ứng dụng.
Ví dụ, nó có thể được sử dụng để tìm “ngày thứ năm đầu tiên của tháng” hoặc “ngày thứ ba kế tiếp”. Lớp TemporalAdjusters bao gồm một tập hợp các phương thức để tạo ra các TemporalAdjusters. Dưới đây là một số phương thức:
- firstDayOfMonth(): Để tìm ngày đầu tiên của tháng.
- firstDayOfNextMonth(): Để tìm ngày đầu tiên của tháng tiếp theo.
- firstInMonth(DayOfWeek): Để tìm ngày đầu tiên trong tháng với một DayOfWeek cụ thể (ví dụ: tìm ngày đầu tiên của tháng mà là Thứ N).
- lastDayOfMonth(): Để tìm ngày cuối cùng của tháng.
- next(DayOfWeek): Để tìm ngày của DayOfWeek kế tiếp (ví dụ: tìm ngày của Thứ N kế tiếp).
- nextOrSame(DayOfWeek): Để tìm ngày của DayOfWeek kế tiếp hoặc cùng một ngày nếu ngày hiện tại đã là DayOfWeek đó.
- previous(DayOfWeek): Để tìm ngày của DayOfWeek trước đó (ví dụ: tìm ngày của Thứ N trước đó).
- previousOrSame(DayOfWeek): Để tìm ngày của DayOfWeek trước đó hoặc cùng một ngày nếu ngày hiện tại đã là DayOfWeek đó.
Các phương thức này giúp thực hiện các tính toán phức tạp liên quan đến ngày tháng một cách dễ dàng trong ứng dụng Java.
TemporalAdjusters cung cấp nhiều cách triển khai, chúng có thể được sử dụng để điều chỉnh các đối tượng DateTime. Dựa trên một ngày cụ thể, bạn có thể tìm ngày đầu tiên của tháng đó.
Ví dụ:
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.time.DayOfWeek;
public class TemporalAdj {
public static void main(String[] args) {
TemporalAdj temporalAdj = new TemporalAdj();
temporalAdj.sampleAdjust();
}
public void sampleAdjust() {
// To display the current date
LocalDate sampleDate = LocalDate.now();
System.out.println("Current date: " + sampleDate);
// To display the next Wednesday from the current date
LocalDate nextWednesday = sampleDate.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
System.out.println("Next Wednesday on: " + nextWednesday);
// To find the second Sunday of the month
LocalDate firstInYear = LocalDate.of(sampleDate.getYear(), sampleDate.getMonthValue(), 1);
LocalDate secondSunday = firstInYear
.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY))
.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println("Second Sunday of the month on: " + secondSunday);
}
}
Tùy chỉnh TemporalAdjusters
Liên quan đến lớp TemporalAdjusters được cung cấp trong API, nó có thể tạo ra phiên bản tùy chỉnh của TemporalAdjuster có nghiệp vụ logic riêng và sử dụng nó trong ứng dụng Java. Điều này có thể hữu ích khi có mô hình lặp lại của việc điều chỉnh trong các trường hợp sử dụng. Những mô hình đó có thể được tách rời bằng cách sử dụng ứng dụng TemporalAdjuster.
Ví dụ:
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
public class CustomTempAdjSample implements TemporalAdjuster {
public Temporal adjustInto(Temporal temporalInput) {
LocalDate loDate = LocalDate.from(temporalInput);
int day = loDate.getDayOfMonth(); // Get the present day
if (day % 2 == 0) { // Check if it's an even day
loDate = loDate.plusDays(1); // Add one day to get the next odd day
} else {
loDate = loDate.plusDays(2); // Add two days to get the next odd day
}
return temporalInput.with(loDate);
}
public static void main(String args[]) {
LocalDate randomDateA = LocalDate.of(2021, Month.MAY, 5);
LocalDate randomDateB = LocalDate.of(2021, Month.MAY, 7);
CustomTempAdjSample nextOddDay = new CustomTempAdjSample();
LocalDate upcomingOddDayA = randomDateA.with(nextOddDay);
LocalDate upcomingOddDayB = randomDateB.with(nextOddDay);
System.out.println("Upcoming Odd Day for " + randomDateA + " is " + upcomingOddDayA);
System.out.println("Upcoming Odd Day for " + randomDateB + " is " + upcomingOddDayB);
}
}
Khả năng tương thích ngược với các phiên bản cũ
Các đối tượng gốc Date và Calendar chứa phương thức toInstant() để chuyển đổi chúng sang API Java Date-Time mới. Sau đó, bạn có thể sử dụng phương thức ofInstant(Instant, ZoneId) để trả về một đối tượng LocalDateTime hoặc ZonedDateTime.
Ví dụ:
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;
import java.time.Instant;
import java.time.ZoneId;
public class Compatibility {
public static void main(String[] args) {
Compatibility bwCompatibility = new Compatibility();
bwCompatibility.sampleBw();
}
public void sampleBw() {
// To display the current date
Date sampleCurDay = new Date();
System.out.println("Desired Current date:");
System.out.println(sampleCurDay);
// To display the instant of the current date
Instant sampleNow = sampleCurDay.toInstant();
ZoneId sampleCurZone = ZoneId.systemDefault();
// To display the current local date
LocalDateTime sampleLoDaTi = LocalDateTime.ofInstant(sampleNow, sampleCurZone);
System.out.println("Desired Current Local date:");
System.out.println(sampleLoDaTi);
// To display the current zoned date
ZonedDateTime sampleZoDaTi = ZonedDateTime.ofInstant(sampleNow, sampleCurZone);
System.out.println("Desired Current zoned date:");
System.out.println(sampleZoDaTi);
}
}
Phân tích cú pháp và định dạng ngày
Chuyển đổi ngày từ chuỗi và định dạng ngày sang chuỗi có thể được thực hiện bằng cách sử dụng lớp java.text.SimpleDateFormat trong Java. Ví dụ:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.text.ParseException;
public class DateFormatExample {
public static void main(String[] args) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
// Formatting the current date to a string
String dateString = dateFormat.format(new Date());
System.out.println("Formatted Date: " + dateString);
try {
// Parsing a date string to a Date object
Date sampleDate = dateFormat.parse("2011-03-25");
System.out.println("Parsed Date: " + sampleDate);
} catch (ParseException e) {
System.err.println("Error parsing date: " + e.getMessage());
}
}
}
TimeZone (java.util.TimeZone)
Lớp TimeZone trong Java đại diện cho các múi giờ. Lớp này được sử dụng trong các tính toán liên quan đến múi giờ. Để lấy một múi giờ từ một đối tượng Calendar, bạn có thể sử dụng phương thức getTimeZone() của đối tượng Calendar. Phương thức này trả về đối tượng TimeZone liên quan đến Calendar cụ thể đó.
Ví dụ:
import java.util.Calendar;
import java.util.TimeZone;
import java.util.GregorianCalendar;
public class CalendarExample {
public static void main(String[] args) {
// Create a GregorianCalendar instance
Calendar cal = new GregorianCalendar();
// Get the TimeZone from the Calendar instance
TimeZone timeZone = cal.getTimeZone();
// Print the TimeZone information
System.out.println("Time Zone ID: " + timeZone.getID());
System.out.println("Time Zone Display Name: " + timeZone.getDisplayName());
}
}
Có hai cách để có được một Thể hiện TimeZone:
TimeZone tz = TimeZone.getDefault();
// hoặc
TimeZone tz = TimeZone.getTimeZone("Europe/Paris");
- Phương thức đầu tiên (TimeZone.getDefault()) trả về múi giờ mặc định cho hệ thống (máy tính hoặc máy chủ) mà chương trình đang chạy.
- Phương thức thứ hai (TimeZone.getTimezone(“Europe/Paris”)) trả về múi giờ tương ứng với múi giờ đã cho (trong trường hợp này là Europe/Paris).
Time-zone Name,ID và OffSet
Ví dụ lấy Name,ID và OffSet:
import java.util.TimeZone;
public class TimeZoneExample {
public static void main(String[] args) {
// Get the default time zone of the system
TimeZone timeZone = TimeZone.getDefault();
// Get the time zone ID, display name, and offset
String timeZoneId = timeZone.getID();
String displayName = timeZone.getDisplayName();
int rawOffset = timeZone.getRawOffset();
// Print the time zone information
System.out.println("Time Zone ID: " + timeZoneId);
System.out.println("Time Zone Display Name: " + displayName);
System.out.println("Time Zone Offset (in milliseconds): " + rawOffset);
}
}
Ví dụ 2:
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class JavaCurTzone {
public static void main(String[] args) {
JavaCurTzone javaCurTzone = new JavaCurTzone();
javaCurTzone.sampleZDtime();
}
public void sampleZDtime() {
// To display the current date and time
ZonedDateTime dateInSingapore = ZonedDateTime.now(ZoneId.of("Asia/Singapore"));
System.out.println("Date: " + dateInSingapore);
ZoneId sampleIdA = ZoneId.of("Asia/Singapore");
System.out.println("ZoneId: " + sampleIdA);
// To display the current Zone
ZoneId sampleCurrentZoneA = ZoneId.systemDefault();
System.out.println("Current Zone: " + sampleCurrentZoneA);
}
}
Chuỗi ngày (Stream Dates)
Java 9 đã giới thiệu một phương thức mới là LocalDate.datesUntil() trả về một chuỗi tuần tự các ngày được sắp xếp. Chuỗi này bắt đầu từ ngày đã cho (bao gồm) đến ngày kết thúc (không bao gồm) với sự tăng dần theo bước là một ngày. Sử dụng datesUntil() giúp tạo ra các chuỗi ngày với khoảng cách cố định dễ dàng.
Ví dụ:
package session10;
import java.time.LocalDate;
import java.util.stream.Stream;
public class DatesUntilMethodDemo {
public static void main(String[] args) {
// Print the days between today and 01 March 2021
Stream<LocalDate> dates = LocalDate.now().datesUntil(LocalDate.parse("2021-03-01"));
dates.forEach(date -> System.out.println(date));
}
}
Output:
2021-02-15
2021-02-16
2021-02-17
2021-02-18
2021-02-19
2021-02-20
2021-02-21
2021-02-22
2021-02-23
2021-02-24
2021-02-25
2021-02-26
2021-02-27
2021-02-28