CodeGym /Các khóa học /C# SELF /Định dạng và phân tích ngày giờ

Định dạng và phân tích ngày giờ

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

1. Định dạng ngày tháng

Nếu bạn nghĩ việc in ra 2025-06-19T17:30:00 trông khá ngầu, thử đưa format này cho bà ngoại hoặc kế toán của bạn xem. Chắc chắn họ sẽ thích cái gì đó đơn giản hơn: 19.06.2025 17:30. Còn mấy đồng nghiệp nói tiếng Anh thì lại mong chờ 06/19/2025 5:30 PM. DevOps và máy móc thì lại khoái 2025-06-19T17:30:00Z. Vậy nên một DateTime trong bộ nhớ chương trình có thể được hiển thị thành hàng chục format khác nhau trên màn hình.

Bài toán ngược cũng kinh điển: user nhập ngày vào ô input ("19.06.2025"), còn mình phải nhận diện nó thành object C# và không bị lẫn lộn ngày với tháng. Tự động hóa, tích hợp, báo cáo — ở đâu cũng cần giải thích đúng chuỗi ngày tháng.

Định dạng cơ bản

C# cho phép chuyển object ngày/giờ (DateTime, DateOnly, TimeOnly, DateTimeOffset) thành chuỗi bằng method .ToString():


DateTime now = DateTime.Now;
Console.WriteLine(now.ToString()); // In ra: 19.06.2025 17:30:25
Định dạng ngày giờ cơ bản

Nếu gọi .ToString() không truyền tham số — sẽ dùng format đặc trưng cho culture hiện tại của hệ thống (ví dụ Windows tiếng Đức sẽ ra format này, còn Windows Mỹ lại ra format khác).

Chuỗi định dạng chuẩn

Bạn có thể chỉ định rõ format in ra, dùng các chuỗi định dạng chuẩn cho ngày giờ:

Định dạng Mô tả Ví dụ in ra
"d"
Ngày ngắn 19.06.2025
"D"
Ngày đầy đủ 19 tháng sáu 2025
"f"
Ngày đầy đủ + giờ ngắn 19 tháng sáu 2025 17:30
"F"
Ngày đầy đủ + giờ đầy đủ 19 tháng sáu 2025 17:30:25
"g"
Ngày và giờ ngắn 19.06.2025 17:30
"G"
Ngày ngắn + giờ đầy đủ 19.06.2025 17:30:25
"t"
Giờ ngắn 17:30
"T"
Giờ đầy đủ 17:30:25
"M"/"m"
Tháng và ngày 19 tháng sáu
"Y"/"y"
Năm và tháng Tháng sáu 2025
"O"/"o"
ISO 8601 (round-trip) 2025-06-19T17:30:25.0000000

Console.WriteLine(now.ToString("d")); // 19.06.2025
Console.WriteLine(now.ToString("F")); // 19 tháng sáu 2025 17:30:25
Console.WriteLine(now.ToString("O")); // 2025-06-19T17:30:25.0000000

Mẫu custom (tự định nghĩa)

Nếu bạn cần format đặc biệt hơn, có thể dùng mẫu tự định nghĩa:

Ký hiệu Ý nghĩa
yyyy Năm, 4 số
yy Năm, 2 số
MM Tháng, 2 số
MMMM Tên tháng
dd Ngày, 2 số
d Ngày, 1-2 số
HH Giờ (24h)
mm Phút
ss Giây
tt AM/PM

Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm")); // 2025-06-19 17:30
Console.WriteLine(now.ToString("dd.MM.yyyy"));       // 19.06.2025
Console.WriteLine(now.ToString("dddd, MMMM d"));     // thứ tư, tháng sáu 19

Khác biệt văn hóa khi định dạng

Nếu bạn muốn kết quả theo style của nước khác hoặc ngôn ngữ khác, hãy dùng overload ToString(string, IFormatProvider):


var enUS = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(now.ToString("D", enUS)); // June 19, 2025
  • Nếu bạn chỉ định cứng mẫu kiểu "MM/dd/yyyy", thì bất kể culture nào bạn vẫn sẽ nhận được "06/19/2025".
  • Nhưng nếu chỉ dùng "d" hoặc "D" — format sẽ phụ thuộc vào culture!

Lưu ý quan trọng khi định dạng

Khi làm việc với định dạng ngày tháng, cần hiểu sự khác biệt giữa format chuẩn và custom. Format chuẩn (như "d", "F", "G") sẽ tự động thích nghi với culture hệ thống, rất tiện cho UI, nhưng có thể gây rắc rối khi trao đổi dữ liệu giữa các hệ thống. Format custom thì kiểm soát hoàn toàn output, nhưng cần cấu hình kỹ hơn.

Đặc biệt chú ý format "O" (hoặc "o") — đây là "round-trip" format, đảm bảo ngày tháng chuyển thành chuỗi rồi chuyển lại sẽ không bị sai lệch. Format này rất quan trọng khi serialize dữ liệu hoặc truyền qua mạng.

2. Phân tích ngày giờ: lấy object từ chuỗi

Phân tích đơn giản: DateTime.Parse

DateTime.Parse — method cố gắng nhận diện chuỗi ngày tháng theo culture của hệ thống.


string input = "19.06.2025";
DateTime parsed = DateTime.Parse(input);
Console.WriteLine(parsed); // 19.06.2025 00:00:00

Nếu chuỗi không hợp lệ — chương trình sẽ crash với exception (không ai tránh được đâu!).

Chỉ định culture


string input = "06/19/2025";
var enUS = new System.Globalization.CultureInfo("en-US");
DateTime dt = DateTime.Parse(input, enUS);
Console.WriteLine(dt); // 19.06.2025 00:00:00

Phân tích an toàn: TryParse


string input = "ngay sai";
bool ok = DateTime.TryParse(input, out DateTime safeDate);
if (!ok)
    Console.WriteLine("Lỗi: không nhận diện được ngày!");

Chỉ định format cứng: ParseExact và TryParseExact


var culture = System.Globalization.CultureInfo.InvariantCulture;
string dateStr = "2025-06-19";

DateTime d = DateTime.ParseExact(dateStr, "yyyy-MM-dd", culture);
Console.WriteLine(d); // 19.06.2025 00:00:00

bool parsedOk = DateTime.TryParseExact(
    "19.06.2025",
    "dd.MM.yyyy",
    System.Globalization.CultureInfo.InvariantCulture,
    System.Globalization.DateTimeStyles.None,
    out DateTime myDate);

Bảng các format phổ biến

Chuỗi Format Object kết quả
"2025-06-19" "yyyy-MM-dd" 19 tháng sáu 2025
"19.06.2025" "dd.MM.yyyy" 19 tháng sáu 2025
"06/19/2025" "MM/dd/yyyy" 19 tháng sáu 2025
"2025-06-19T14:15:16" "s" 19 tháng sáu 2025 14:15:16

Làm việc với DateTimeStyles

Khi phân tích, bạn có thể kiểm soát thêm hành vi qua tham số DateTimeStyles. Enum này cho phép cấu hình parser hiểu input thế nào. Ví dụ, DateTimeStyles.AssumeUniversal bắt parser coi giờ là UTC nếu không có offset. DateTimeStyles.AllowWhiteSpaces cho phép bỏ qua khoảng trắng thừa trong chuỗi. Các setting này rất hữu ích khi làm với dữ liệu từ nguồn ngoài, format không đoán trước được.

3. Định dạng và phân tích DateOnly, TimeOnly

Các kiểu mới DateOnly và TimeOnly giờ hay dùng để lưu ngày/giờ mà không cần chi tiết dư thừa.

Định dạng


DateOnly birthday = new DateOnly(2000, 6, 19);
Console.WriteLine(birthday.ToString("dd MMMM yyyy")); // 19 tháng sáu 2000

Phân tích


var d = DateOnly.ParseExact("19.06.2000", "dd.MM.yyyy");
Console.WriteLine(d.Day); // 19

Các method cho TimeOnly cũng y chang (chỉ khác là mẫu chỉ liên quan đến giờ/phút/giây):

TimeOnly t = TimeOnly.ParseExact("23:59", "HH:mm");
Console.WriteLine(t.Hour); // 23

Lợi ích của DateOnly và TimeOnly

Dùng DateOnly và TimeOnly thay cho DateTime có vài lợi ích quan trọng. Đầu tiên là rõ ràng về ý nghĩa — nếu bạn chỉ cần ngày không cần giờ (ví dụ ngày sinh), DateOnly thể hiện rõ ý đồ đó. Thứ hai, nó giúp tránh lỗi về múi giờ khi dùng DateTime. Thứ ba, các kiểu này chiếm ít bộ nhớ hơn trong RAM và database.

Định dạng và phân tích có tính đến múi giờ

Nếu bạn lưu giờ có thông tin offset — hãy dùng DateTimeOffset. Cái này cực kỳ quan trọng cho hệ thống quốc tế, phân tán. Tất cả method định dạng và phân tích đều giống nhau, chỉ là giờ bạn kiểm soát được offset:


DateTimeOffset meeting = new DateTimeOffset(2025, 6, 19, 17, 30, 0, TimeSpan.FromHours(3));
Console.WriteLine(meeting.ToString("o")); // 2025-06-19T17:30:00.0000000+03:00

string input = "2025-06-19T17:30:00+03:00";
var parsedOffset = DateTimeOffset.Parse(input);
Console.WriteLine(parsedOffset.Offset); // 03:00:00

4. Lưu ý thực tế và lỗi thường gặp

Một cái bẫy là nhầm "ngày" với "tháng" khi phân tích format quốc tế. Ví dụ, chuỗi "01/02/2025" ở Mỹ là 2 tháng 1, còn ở đa số nước châu Âu là 1 tháng 2 (bất ngờ chưa!).

Cũng hay quên ảnh hưởng của culture: nếu app chạy trên server ở Đức, còn user đến từ nhiều nước, format ngày từ database có thể bị hiểu khác nhau trên mỗi server.

Lỗi phổ biến là dùng .ToString() mà không chỉ định culture/format cho log và file trao đổi: kết quả có thể thay đổi khi chuyển sang OS khác hoặc app chạy dưới user Windows khác.

Khuyến nghị khi làm việc với ngày tháng

  • Để lưu trữ nội bộ và trao đổi dữ liệu, luôn dùng culture bất biến (CultureInfo.InvariantCulture) hoặc format chỉ định rõ ràng.
  • Cho UI, hãy dùng culture của user hoặc cho phép họ chọn format ưa thích.
  • Khi làm việc với API và database, ưu tiên format ISO 8601 — chuẩn quốc tế.
  • Luôn validate input: kiểm tra ngày có tồn tại, nằm trong khoảng hợp lý không.

Làm việc với nhiều nguồn dữ liệu

Khi tích hợp với hệ thống ngoài, bạn sẽ gặp ngày tháng ở nhiều format khác nhau. Có hệ thống gửi ngày kiểu Unix timestamp (số giây từ 1/1/1970), có hệ thống lại gửi chuỗi theo format quốc gia. Quan trọng là phải thống nhất format trao đổi và luôn kiểm tra kết quả phân tích.

Cũng nên nhớ, một số format có thể gây hiểu nhầm. Ví dụ, "12/13/2025" chắc chắn là 13 tháng mười hai 2025, nhưng "12/11/2025" có thể là 12 tháng mười một hoặc 11 tháng mười hai tùy culture. Trường hợp này nên dùng format ít gây nhầm lẫn hơn hoặc chỉ định rõ culture khi phân tích.

2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Định dạng cơ bản cho ngày và giờ
Định dạng cơ bản cho ngày và giờ
2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Phân tích ngày tháng an toàn từ chuỗi
Phân tích ngày tháng an toàn từ chuỗi
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION