Lớp java.time.DayOfWeek
Lớp DayOfWeek trong gói java.time của Java là một kiểu liệt kê (enum) biểu diễn 7 ngày trong tuần: Thứ Hai, Thứ Ba, Thứ Tư, Thứ Năm, Thứ Sáu, Thứ Bảy và Chủ Nhật.
Ⅰ. Đặc điểm của lớp DayOfWeek
↳ Mỗi ngày trong tuần có tên theo chữ (ví dụ: Thứ Hai) và một giá trị kiểu số nguyên (int).
↳ Giá trị int tuân theo chuẩn ISO-8601, từ 1 (Thứ Hai) đến 7 (Chủ Nhật).
↳ Nên sử dụng tên ngày trong tuần (enum) thay vì giá trị số int để đảm bảo mã dễ đọc.
↳ DayOfWeek cung cấp phương thức để truy cập vào tên của ngày theo ngôn ngữ (ví dụ: "Thứ Hai" trong tiếng Việt).
↳ Lưu ý rằng một số ngôn ngữ có thể đánh số thứ tự ngày trong tuần theo cách khác (ví dụ: Chủ Nhật là 1), nhưng DayOfWeek không hỗ trợ điều này. Sử dụng lớp WeekFields để lấy số thứ tự tuần theo ngôn ngữ.
↳ Sử dụng phương thức getValue() để lấy giá trị số int của ngày trong tuần, không nên dùng phương thức ordinal().
↳ DayOfWeek là một khái niệm chung trong nhiều hệ thống lịch. Do đó, nó có thể được sử dụng bởi bất kỳ hệ thống lịch nào có khái niệm ngày trong tuần tương đương với lịch ISO.
↳ DayOfWeek là một kiểu liệt kê bất biến (immutable) và an toàn cho nhiều luồng (thread-safe).
Ⅱ. Khai báo lớp DayOfWeek trong Java
Để sử dụng lớp DayOfWeek và các lớp khác trong gói java.time, bạn cần thêm câu lệnh import vào đầu file Java của mình.
Cú pháp câu lệnh import:
Cú pháp
import java.time.DayOfWeek;
Cú pháp khai báo lớp DayOfWeek:
Cú pháp
public enum DayOfWeek
extends Enum<DayOfWeek>
implements TemporalAccessor, TemporalAdjuster
Dưới đây là giải thích chi tiết về cú pháp khai báo này:
↳ public: Lớp này có thể được truy cập từ bất kỳ đâu trong chương trình, không bị giới hạn phạm vi.
↳ enum DayOfWeek: Đây là một enum (liệt kê) công khai có tên là DayOfWeek. enum là một kiểu dữ liệu đặc biệt dùng để định nghĩa một tập hợp các hằng số, và trong trường hợp này, DayOfWeek đại diện cho các ngày trong tuần (Chủ nhật, Thứ hai, ..., Thứ bảy).
extends Enum<DayOfWeek>: Điều này cho thấy DayOfWeek là một enum và kế thừa từ lớp Enum. Trong Java, tất cả các enum đều tự động kế thừa từ lớp Enum. Enum<DayOfWeek>chỉ định rằng DayOfWeek là một kiểu enum với các giá trị kiểu DayOfWeek.
implements TemporalAccessor, TemporalAdjuster
Lớp DayOfWeek thực hiện (implements) các giao diện TemporalAccessor, TemporalAdjuster. Điều này có nghĩa là lớp DayOfWeek phải cung cấp các phương thức được khai báo trong những giao diện này.
↳ implements TemporalAccessor: Giao diện này cho phép DayOfWeek truy cập các thông tin liên quan đến thời gian.
↳ implements TemporalAdjuster: Giao diện này cho phép DayOfWeek thực hiện các điều chỉnh liên quan đến thời gian, chẳng hạn như điều chỉnh ngày tháng.
Các hằng số Enum
DayOfWeek cung cấp các hằng số enum để biểu diễn các ngày cụ thể trong tuần:
↳ SUNDAY: Biểu diễn ngày Chủ Nhật.
↳ MONDAY: Biểu diễn ngày Thứ Hai.
↳ TUESDAY: Biểu diễn ngày Thứ Ba.
↳ WEDNESDAY: Biểu diễn ngày Thứ Tư.
↳ THURSDAY: Biểu diễn ngày Thứ Năm.
↳ FRIDAY: Biểu diễn ngày Thứ Sáu.
↳ SATURDAY: Biểu diễn ngày Thứ Bảy.
Lưu ý rằng mỗi hằng số này là một đối tượng duy nhất (singleton) đại diện cho ngày tương ứng trong tuần.
Ⅲ. Các phương thức của lớp DayOfWeek
Lớp DayOfWeek cung cấp nhiều phương thức để thao tác với ngày trong tuần. Việc phân nhóm các phương thức theo chức năng sẽ giúp bạn hiểu rõ hơn về cách sử dụng lớp DayOfWeek. Dưới đây là cách phân nhóm các phương thức phổ biến của lớp DayOfWeek:
Tạo đối tượng DayOfWeek
↳ of(int dayOfWeek): Tạo một DayOfWeek từ một số nguyên biểu diễn thứ trong tuần.
↳ values(): Trả về một mảng chứa tất cả các giá trị có thể của DayOfWeek.
↳ valueOf(String name): Tạo một DayOfWeek từ tên của nó (ví dụ: "MONDAY").
Dưới đây là một ví dụ về cách sử dụng ba phương thức tạo đối trượng DayOfWeek trong một lớp Java:
Ví dụ: Example.java
import java.time.DayOfWeek;
public class Example {
public static void main(String[] args) {
// Tạo một DayOfWeek từ một số nguyên (1 đến 7)
DayOfWeek day1 = DayOfWeek.of(1); // Chủ nhật
DayOfWeek day2 = DayOfWeek.of(5); // Thứ năm
// Hiển thị kết quả
System.out.println("DayOfWeek.of(1): " + day1);
System.out.println("DayOfWeek.of(5): " + day2);
// Lấy tất cả các giá trị có thể của DayOfWeek
DayOfWeek[] days = DayOfWeek.values();
System.out.println("Tất cả các ngày trong tuần:");
for (DayOfWeek day : days) {
System.out.println(day);
}
// Tạo DayOfWeek từ tên của nó
DayOfWeek monday = DayOfWeek.valueOf("MONDAY");
System.out.println("DayOfWeek.valueOf(\"MONDAY\"): " + monday);
}
}
Kết quả của chương trình là:
DayOfWeek.of(5): FRIDAY
Tất cả các ngày trong tuần:
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
DayOfWeek.valueOf("MONDAY"): MONDAY
Trong ví dụ trên, các phương thức được sử dụng để tạo đối tượng DayOfWeek từ số nguyên, lấy tất cả các giá trị có thể của DayOfWeek, và tạo đối tượng DayOfWeek từ tên của nó.
Lấy thông tin
↳ get(TemporalField field): Lấy giá trị của một trường thời gian cụ thể (như thứ trong tuần).
↳ getLong(TemporalField field): Giống get nhưng trả về giá trị kiểu long.
↳ getValue(): Lấy giá trị số nguyên biểu diễn thứ trong tuần.
↳ getDisplayName(TextStyle style, Locale locale): Lấy tên hiển thị của ngày trong tuần.
↳ isSupported(TemporalField field): Kiểm tra xem trường thời gian có được hỗ trợ hay không.e.
↳ range(TemporalField field): Lấy phạm vi các giá trị hợp lệ cho một trường thời gian.
Dưới đây là một ví dụ về cách sử dụng các phương thức của lớp DayOfWeek để lấy thông tin về ngày trong tuần trong Java:
Ví dụ: Example.java
import java.time.DayOfWeek;
import java.time.format.TextStyle;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class Example {
public static void main(String[] args) {
// Tạo đối tượng DayOfWeek
DayOfWeek day = DayOfWeek.WEDNESDAY;
// Lấy giá trị của một trường thời gian cụ thể
int dayValue = day.get(ChronoField.DAY_OF_WEEK);
System.out.println("get(ChronoField.DAY_OF_WEEK): " + dayValue);
// Lấy giá trị của trường thời gian dưới dạng long
long dayValueLong = day.getLong(ChronoField.DAY_OF_WEEK);
System.out.println("getLong(ChronoField.DAY_OF_WEEK): " + dayValueLong);
// Lấy giá trị số nguyên biểu diễn thứ trong tuần
int numericValue = day.getValue();
System.out.println("getValue(): " + numericValue);
// Lấy tên hiển thị của ngày trong tuần
String displayName = day.getDisplayName(TextStyle.FULL, Locale.ENGLISH);
System.out.println("getDisplayName(TextStyle.FULL, Locale.ENGLISH): " + displayName);
// Kiểm tra xem trường thời gian có được hỗ trợ hay không
boolean isSupported = day.isSupported(ChronoField.DAY_OF_WEEK);
System.out.println("isSupported(ChronoField.DAY_OF_WEEK): " + isSupported);
// Lấy phạm vi các giá trị hợp lệ cho một trường thời gian
System.out.println("range(ChronoField.DAY_OF_WEEK): " + day.range(ChronoField.DAY_OF_WEEK));
}
}
Kết quả của chương trình là:
getLong(ChronoField.DAY_OF_WEEK): 3
getValue(): 3
getDisplayName(TextStyle.FULL, Locale.ENGLISH): Wednesday
isSupported(ChronoField.DAY_OF_WEEK): true
range(ChronoField.DAY_OF_WEEK): 1 - 7
Trong ví dụ trên, các phương thức được sử dụng để lấy thông tin về DayOfWeek, bao gồm giá trị của trường thời gian, giá trị số nguyên, tên hiển thị, kiểm tra hỗ trợ, và phạm vi giá trị hợp lệ.
So sánh và kiểm tra
↳ compareTo(DayOfWeek other): So sánh hai DayOfWeek với nhau.
↳ equals(Object obj): Kiểm tra hai DayOfWeek có bằng nhau không.
Dưới đây là ví dụ về cách sử dụng các phương thức compareTo() và phương thức equals() của lớp DayOfWeek để so sánh và kiểm tra ngày trong tuần:
Ví dụ: Example.java
import java.time.DayOfWeek;
public class Example {
public static void main(String[] args) {
// Tạo các đối tượng DayOfWeek
DayOfWeek monday = DayOfWeek.MONDAY;
DayOfWeek wednesday = DayOfWeek.WEDNESDAY;
DayOfWeek anotherWednesday = DayOfWeek.WEDNESDAY;
// So sánh hai DayOfWeek với nhau
int comparisonResult = monday.compareTo(wednesday);
System.out.println("compareTo(WEDNESDAY): " + comparisonResult); // Kết quả âm vì MONDAY trước WEDNESDAY
// Kiểm tra hai DayOfWeek có bằng nhau không
boolean isEqual = wednesday.equals(anotherWednesday);
System.out.println("equals(another WEDNESDAY): " + isEqual); // Kết quả true vì cả hai đều là WEDNESDAY
}
}
Kết quả của chương trình là:
equals(another WEDNESDAY): true
Trong ví dụ trên, phương thức compareTo() được sử dụng để so sánh hai đối tượng DayOfWeek và phương thức equals() để kiểm tra sự bằng nhau giữa hai đối tượng.
Điều chỉnh
↳ plus(long days): Cộng thêm một số ngày.
↳ minus(long days): Trừ đi một số ngày.
↳ with(Temporal temporal): Điều chỉnh đối tượng thời gian (Temporal) được cung cấp để có cùng ngày trong tuần với DayOfWeek hiện tại.
Dưới đây là ví dụ về cách sử dụng các phương thức plus(), minus() và adjustInto() của lớp DayOfWeek để điều chỉnh ngày trong tuần:
Ví dụ: Example.java
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
public class Example {
public static void main(String[] args) {
// Tạo đối tượng DayOfWeek
DayOfWeek dayOfWeek = DayOfWeek.MONDAY;
// Cộng thêm một số ngày
DayOfWeek newDayPlus = dayOfWeek.plus(3); // Tăng thêm 3 ngày
System.out.println("plus(3 days): " + newDayPlus); // Kết quả: THURSDAY
// Trừ đi một số ngày
DayOfWeek newDayMinus = dayOfWeek.minus(2); // Giảm bớt 2 ngày
System.out.println("minus(2 days): " + newDayMinus); // Kết quả: SATURDAY
// Điều chỉnh một đối tượng thời gian khác về ngày trong tuần này
LocalDate date = LocalDate.of(2024, 7, 22); // Ngày cụ thể
// Điều chỉnh ngày trong tuần gần nhất của LocalDate
LocalDate adjustedDate = date.with(TemporalAdjusters.next(dayOfWeek)); // Hoặc: date.with(TemporalAdjusters.previous(dayOfWeek))
System.out.println("with(date): " + adjustedDate); // Kết quả: ngày thứ Hai gần nhất
}
}
Kết quả của chương trình là:
minus(2 days): SATURDAY
with(date): 2024-07-29
Trong ví dụ trên, phương thức plus() và minus() được sử dụng để điều chỉnh ngày trong tuần, còn with điều chỉnh một ngày cụ thể để nó trở thành ngày trong tuần mong muốn.
Truy vấn
↳ query(TemporalQuery query): Thực hiện một truy vấn tùy chỉnh trên DayOfWeek.
Dưới đây là ví dụ về cách sử dụng phương thức query() với TemporalQuery() trên đối tượng DayOfWeek:
Ví dụ: Example.java
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQuery;
public class Example {
public static void main(String[] args) {
// Tạo đối tượng DayOfWeek
DayOfWeek dayOfWeek = DayOfWeek.WEDNESDAY;
// Tạo một truy vấn tùy chỉnh để lấy số nguyên biểu diễn thứ trong tuần từ DayOfWeek
TemporalQuery<Integer> query = new TemporalQuery<>() {
@Override
public Integer queryFrom(TemporalAccessor temporal) {
if (temporal instanceof DayOfWeek) {
DayOfWeek dow = (DayOfWeek) temporal;
return dow.getValue(); // Trả về giá trị số nguyên của ngày trong tuần
}
return null;
}
};
// Thực hiện truy vấn
Integer dayOfWeekValue = dayOfWeek.query(query);
System.out.println("Giá trị ngày trong tuần: " + dayOfWeekValue); // Kết quả: 3 (tương ứng với Wednesday)
// Cũng có thể thực hiện truy vấn trên LocalDate
LocalDate date = LocalDate.of(2024, 7, 24); // Ngày cụ thể (Wednesday)
Integer dayOfWeekFromDate = date.query(query);
System.out.println("Giá trị ngày trong tuần từ LocalDate: " + dayOfWeekFromDate); // Kết quả: 3
}
}
Kết quả của chương trình là:
Giá trị ngày trong tuần từ LocalDate: null
Trong ví dụ trên, phương thức query() được sử dụng để thực hiện truy vấn tùy chỉnh để lấy giá trị số nguyên của ngày trong tuần từ đối tượng DayOfWeek và LocalDate.
Các ngoại lệ thường gặp khi sử dụng lớp DayOfWeek trong Java
Dưới đây là các ngoại lệ thường gặp và nguyên nhân của chúng:
Ngoại lệ DateTimeException
↳ Nguyên nhân: Thường xảy ra khi bạn cung cấp một giá trị không hợp lệ cho DayOfWeek. Ví dụ, khi cố gắng tạo một DayOfWeek từ một số nguyên không nằm trong khoảng từ 1 đến 7.
↳ Ví dụ: Khi gọi phương thức DayOfWeek.of(8), sẽ xảy ra DateTimeException vì 8 không phải là một giá trị hợp lệ cho DayOfWeek.
Ngoại lệ UnsupportedTemporalTypeException
↳ Nguyên nhân: Xảy ra khi bạn cố gắng sử dụng một phương thức không hỗ trợ cho đối tượng DayOfWeek. Ví dụ, khi sử dụng phương thức get với một trường thời gian không hỗ trợ.
↳ Ví dụ: Khi gọi dayOfWeek.get(ChronoField.YEAR), bạn sẽ nhận được UnsupportedTemporalTypeException vì DayOfWeek không hỗ trợ trường thời gian YEAR.
Ngoại lệ ClassCastException
↳ Nguyên nhân: Xảy ra khi bạn thực hiện một phép chuyển kiểu không hợp lệ. Ví dụ, khi cố gắng chuyển một đối tượng TemporalAccessor không phải là DayOfWeek thành DayOfWeek.
↳ Ví dụ: Khi gọi DayOfWeek.MONDAY.query(temporal) và temporal không phải là một đối tượng DayOfWeek, sẽ xảy ra ClassCastException.
Ngoại lệ NullPointerException
↳ Nguyên nhân: Thường xảy ra khi bạn truyền giá trị null vào một phương thức yêu cầu một đối tượng không rỗng.
↳ Ví dụ: Khi gọi dayOfWeek.getDisplayName(null, Locale.ENGLISH) với tham số TextStyle là null, sẽ dẫn đến NullPointerException.
Lưu ý:
Khi làm việc với DayOfWeek, việc kiểm tra dữ liệu đầu vào và các thao tác ngày tháng là rất quan trọng để tránh các ngoại lệ. Sử dụng các cơ chế kiểm tra và xử lý ngoại lệ để cung cấp thông báo lỗi hoặc xử lý các tình huống bất thường để làm cho ứng dụng của bạn ổn định và dễ duy trì hơn.