CodeGym /Các khóa học /JAVA 25 SELF /Định dạng và phân tích chuỗi ngày: DateTimeFormatter

Định dạng và phân tích chuỗi ngày: DateTimeFormatter

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. DateTimeFormatter: là gì và dùng để làm gì

Trong các chương trình thực tế, ngày tháng hiếm khi chỉ tồn tại bên trong mã. Thông thường chúng ta cần:

  • Chuyển thành chuỗi để in ra console, màn hình hoặc tệp (ví dụ, "01.06.2025 14:30").
  • Phân tích chuỗi, tức là biến chuỗi do người dùng nhập hoặc đến từ tệp trở lại thành đối tượng ngày/giờ.

Để làm điều đó, Java có một công cụ mạnh mẽ và tiện dụng — lớp java.time.format.DateTimeFormatter.

Có thể xem DateTimeFormatter như một “người phiên dịch” giữa các đối tượng thời gian (LocalDate, LocalDateTime, ZonedDateTime, Instant, v.v.) và các chuỗi. Nó có thể:

  • Biến các đối tượng ngày/giờ thành chuỗi theo định dạng mong muốn (format — định dạng).
  • Biến chuỗi thành các đối tượng ngày/giờ (parse — phân tích).

2. Các formatter tiêu chuẩn: nhanh và đơn giản

Java đã chuẩn bị sẵn cho chúng ta một bộ formatter tiêu chuẩn, bao phủ các định dạng ISO phổ biến nhất (các tiêu chuẩn quốc tế cho ngày và giờ).

Một vài cái tiêu biểu:

Formatter Ví dụ chuỗi Mô tả
DateTimeFormatter.ISO_LOCAL_DATE
2025-06-01 Chỉ ngày (năm-tháng-ngày)
DateTimeFormatter.ISO_LOCAL_TIME
14:30:00 Chỉ thời gian (giờ:phút:giây)
DateTimeFormatter.ISO_LOCAL_DATE_TIME
2025-06-01T14:30:00 Ngày và giờ không có múi giờ
DateTimeFormatter.ISO_ZONED_DATE_TIME
2025-06-01T14:30:00+03:00[Europe/Minsk] Ngày, giờ và múi giờ

Ví dụ sử dụng formatter tiêu chuẩn

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class FormatterDemo {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        // Định dạng ngày thành chuỗi
        String text = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
        System.out.println(text); // Ví dụ: 2025-06-01

        // Phân tích chuỗi về lại ngày
        LocalDate parsed = LocalDate.parse("2025-06-01", DateTimeFormatter.ISO_LOCAL_DATE);
        System.out.println(parsed); // 2025-06-01
    }
}

Ẩn dụ

Nếu Java là một quán cà phê, các formatter tiêu chuẩn chính là “americano”, “latte” và “espresso”. Nhanh, chuẩn mực, nhưng đôi khi bạn sẽ muốn thứ gì đó đặc biệt!

3. Mẫu tùy chỉnh: DateTimeFormatter.ofPattern

Đôi khi các định dạng tiêu chuẩn là chưa đủ. Ví dụ, bạn cần in ngày ở dạng "01.06.2025 14:30", chứ không phải "2025-06-01T14:30:00". Khi đó ta có thể tạo mẫu riêng bằng phương thức DateTimeFormatter.ofPattern(String pattern).

Cú pháp mẫu

Trong mẫu có các ký tự đặc biệt:

  • y — năm (yyyy2025)
  • M — tháng (MM06)
  • d — ngày (dd01)
  • H — giờ (định dạng 24 giờ, HH14)
  • m — phút (mm30)
  • s — giây (ss00)

Ví dụ về mẫu

Mẫu Kết quả ví dụ
"dd.MM.yyyy"
01.06.2025
"yyyy/MM/dd"
2025/06/01
"dd.MM.yyyy HH:mm"
01.06.2025 14:30
"yyyy-MM-dd HH:mm:ss"
2025-06-01 14:30:00
"d MMMM yyyy"
1 tháng 6 2025 (với locale tiếng Nga)

Ví dụ: định dạng ngày và giờ

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class CustomFormatDemo {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2025, 6, 1, 14, 30);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
        String text = dt.format(formatter);
        System.out.println(text); // 01.06.2025 14:30
    }
}

Ví dụ: phân tích chuỗi thành ngày

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class ParseDemo {
    public static void main(String[] args) {
        String input = "01.06.2025 14:30";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
        LocalDateTime dt = LocalDateTime.parse(input, formatter);
        System.out.println(dt); // 2025-06-01T14:30
    }
}

Lưu ý: mẫu phải khớp chính xác với chuỗi! Nếu chuỗi có giây — hãy thêm :ss vào mẫu.

4. Định dạng: biến ngày/giờ thành chuỗi

Sơ đồ tổng quát

  1. Tạo đối tượng cần thiết (LocalDate, LocalDateTime, ZonedDateTime, v.v.).
  2. Tạo hoặc chọn formatter phù hợp.
  3. Gọi phương thức format(DateTimeFormatter) trên đối tượng, nhận về chuỗi.

Ví dụ: in ngày theo nhiều định dạng

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class MultiFormatDemo {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2025, 6, 1);

        // Chuẩn ISO
        System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2025-06-01

        // Định dạng tùy chỉnh
        DateTimeFormatter rusFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        System.out.println(date.format(rusFormat)); // 01.06.2025

        // Kiểu Mỹ (US)
        DateTimeFormatter usFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy");
        System.out.println(date.format(usFormat)); // 06/01/2025
    }
}

Định dạng thời gian

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class TimeFormatDemo {
    public static void main(String[] args) {
        LocalTime time = LocalTime.of(14, 30, 5);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
        System.out.println(time.format(formatter)); // 14:30:05
    }
}

5. Phân tích chuỗi: biến chuỗi thành ngày/giờ

Sơ đồ tổng quát

  1. Nhận chuỗi (ví dụ, từ người dùng).
  2. Tạo formatter với cùng mẫu như chuỗi.
  3. Gọi phương thức tĩnh parse() hoặc phương thức parse() của formatter.

Ví dụ: phân tích ngày

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class ParseDateDemo {
    public static void main(String[] args) {
        String input = "01.06.2025";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        LocalDate date = LocalDate.parse(input, formatter);
        System.out.println(date); // 2025-06-01
    }
}

Ví dụ: phân tích ngày và giờ

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class ParseDateTimeDemo {
    public static void main(String[] args) {
        String input = "01.06.2025 14:30";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
        LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
        System.out.println(dateTime); // 2025-06-01T14:30
    }
}

6. Xử lý lỗi khi phân tích chuỗi

Parsing có thể khó chịu. Nếu chuỗi không khớp với mẫu, Java sẽ ném ngoại lệ DateTimeParseException. Đây là tình huống bình thường, chẳng hạn khi người dùng nhập sai ngày.

Ví dụ: xử lý lỗi khi phân tích

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class ParseErrorDemo {
    public static void main(String[] args) {
        String input = "32.13.2025"; // Ngày không hợp lệ
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        try {
            LocalDate date = LocalDate.parse(input, formatter);
            System.out.println(date);
        } catch (DateTimeParseException ex) {
            System.out.println("Lỗi phân tích chuỗi: " + ex.getMessage());
        }
    }
}

Quan trọng: luôn xử lý những lỗi như vậy khi làm việc với dữ liệu nhập từ người dùng!

7. Thực hành: chuyển đổi ngày cho người dùng

Giả sử, trong ứng dụng học tập của chúng ta có yêu cầu: người dùng nhập ngày sinh theo định dạng "dd.MM.yyyy", và chương trình phải xuất ngày theo định dạng "yyyy/MM/dd", đồng thời hiển thị thứ trong tuần.

Ví dụ

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;

public class BirthdayFormatDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Nhập ngày sinh (dd.MM.yyyy): ");
        String input = scanner.nextLine();

        DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd");

        try {
            LocalDate birthday = LocalDate.parse(input, inputFormat);
            String formatted = birthday.format(outputFormat);
            System.out.println("Ngày của bạn ở định dạng mới: " + formatted);
            System.out.println("Thứ trong tuần: " + birthday.getDayOfWeek()); // Ví dụ: SATURDAY
        } catch (DateTimeParseException ex) {
            System.out.println("Lỗi: định dạng ngày không hợp lệ!");
        }
    }
}

8. Bản địa hóa: ngôn ngữ ảnh hưởng đến định dạng như thế nào

Với DateTimeFormatter, bạn không chỉ thay đổi thứ tự số mà còn có thể in tên tháng bằng chữ, thứ trong tuần, v.v. Locale (ngôn ngữ và vùng) sẽ được tính đến.

Ví dụ: in tên tháng bằng chữ (tiếng Nga)

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class LocaleDemo {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2025, 6, 1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", new Locale("ru"));
        System.out.println(date.format(formatter)); // 1 tháng 6 2025
    }
}

Ví dụ: locale tiếng Anh

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class LocaleEnDemo {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2025, 6, 1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ENGLISH);
        System.out.println(date.format(formatter)); // 1 June 2025
    }
}

Mẹo: nếu bạn muốn tháng và thứ hiển thị đúng ngôn ngữ — hãy chỉ định locale một cách tường minh!

9. Những lỗi thường gặp khi định dạng và phân tích chuỗi ngày

Lỗi № 1: Mẫu không khớp với chuỗi.
Nếu chuỗi "01.06.2025 14:30", còn mẫu là "dd.MM.yyyy", việc phân tích sẽ thất bại. Mẫu phải khớp chính xác với chuỗi.

Lỗi № 2: Nhầm ký tự mẫu.
MM — tháng, mm — phút. Nếu viết "dd.mm.yyyy", Java sẽ hiểu bạn muốn phút và sẽ báo lỗi. Với tháng, luôn dùng chữ hoa M.

Lỗi № 3: Không xử lý ngoại lệ khi phân tích.
Nếu không bắt DateTimeParseException, chương trình có thể dừng đột ngột khi nhập sai. Luôn xử lý các lỗi này.

Lỗi № 4: Không chỉ định locale khi dùng tên bằng chữ.
Nếu dùng mẫu có tháng bằng chữ (MMMM) mà không chỉ định locale, Java có thể dùng ngôn ngữ mặc định (ví dụ, tiếng Anh). Hãy luôn đặt locale rõ ràng.

Lỗi № 5: Dùng các lớp cũ (SimpleDateFormat, Date) trong dự án mới.
Hãy nhớ: trong mã hiện đại, hãy dùng java.timeDateTimeFormatter.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION