Menu

Định dạng DateTime trong C#: chuỗi định dạng, culture, ISO 8601

Cách định dạng DateTime thành chuỗi trong C#: các chuỗi định dạng chuẩn (d, D, o, s, u, t), mẫu tùy chỉnh như yyyy-MM-dd HH:mm:ss, bảng đầy đủ các ký hiệu định dạng, culture thay đổi đầu ra thế nào, ISO 8601 round-trip với "o", và các lỗi nhầm mm với MM, hh với HH.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

DateTime.ToString(format) biến một ngày thành văn bản. Định dạng có thể là chuỗi định dạng chuẩn (một chữ cái như d hoặc o, có mẫu cụ thể do culture quyết định) hoặc một mẫu tùy chỉnh ghép từ các ký hiệu định dạng (format specifier) như yyyy, MM và HH. Các chuỗi này cũng dùng được trong chuỗi nội suy, $"{date:yyyy-MM-dd}", và trong string.Format.

Đầu ra:

2026-10-09
2026-10-09 18:30:07
09/10/2026
Oct 9, 2026
Friday, October 9
6:30 PM
18:30:07.045
Shipped 2026-10-09 at 18:30

Các ví dụ trên trang này truyền CultureInfo.InvariantCulture để đầu ra giống nhau trên mọi máy; nếu không có nó, ToString dùng culture hiện tại, có thể làm thay đổi tên tháng, dấu phân cách và thậm chí cả lịch.

Ký hiệu định dạng tùy chỉnh

Định dạng tùy chỉnh là một mẫu trong đó một số chữ cái đại diện cho các phần của ngày. Chúng phân biệt chữ hoa chữ thường: M là tháng còn m là phút, H là giờ dạng 24 giờ còn h là giờ dạng 12 giờ.

Ký hiệuÝ nghĩaVí dụ với 2026-10-09 18:30:07.045
yyyyNăm, 4 chữ số2026
yyNăm, 2 chữ số26
MMMMTên tháng đầy đủOctober
MMMTên tháng viết tắtOct
MMTháng, 2 chữ số10
MTháng, 1 hoặc 2 chữ số10
ddddTên thứ đầy đủFriday
dddTên thứ viết tắtFri
ddNgày trong tháng, 2 chữ số09
dNgày trong tháng, 1 hoặc 2 chữ số (trong một mẫu)9
HHGiờ, từ 00 đến 2318
HGiờ, từ 0 đến 2318
hhGiờ, từ 01 đến 1206
hGiờ, từ 1 đến 126
mmPhút, 2 chữ số30
ssGiây, 2 chữ số07
fffMili giây045
fffffffTick (bảy chữ số phần thập phân)0450000
ttKý hiệu AM/PMPM
zzzĐộ lệch so với UTC (DateTimeOffset hoặc giờ địa phương)+02:00
KThông tin múi giờ: Z, một độ lệch, hoặc không gì cảZ (với giá trị UTC)
/Dấu phân cách ngày của culture/ hoặc . hoặc -
:Dấu phân cách giờ của culture:
'text' hoặc \cVăn bản hoặc ký tự nguyên văn'at'

Mọi ký tự khác được giữ nguyên. Kể cả những chữ cái không phải ký hiệu định dạng, và đó là lý do "YYYY-DD" lặng lẽ in ra YYYY-DD: .NET không có ký hiệu Y hay D viết hoa.

Một chữ cái đứng riêng được hiểu là định dạng chuẩn, không phải tùy chỉnh: ToString("d") là mẫu ngày dạng ngắn, không phải số ngày. Để chỉ lấy ngày, viết ToString("%d") hoặc dùng property Day.

Đầu ra:

10/09/2026
9
20261009_183007
Week of Oct 9
18h30
2026-10-09T18:30:07
YYYY-DD

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

Định dạng chuẩn là các chữ cái đơn có mẫu thực tế do culture định nghĩa. Chúng là lựa chọn đúng cho văn bản hiển thị cho người dùng, vì mỗi culture tự động có quy ước riêng của mình.

Đầu ra:

d  10/09/2026
D  Friday, 09 October 2026
f  Friday, 09 October 2026 18:30
g  10/09/2026 18:30
G  10/09/2026 18:30:07
M  October 09
Y  2026 October
t  18:30
T  18:30:07
o  2026-10-09T18:30:07.0000000Z
s  2026-10-09T18:30:07
u  2026-10-09 18:30:07Z
r  Fri, 09 Oct 2026 18:30:07 GMT
en-US d: 10/9/2026, D: Friday, October 9, 2026
MãTênPhụ thuộc culture?
d / DNgày dạng ngắn / dàiCó
t / TGiờ dạng ngắn / dàiCó
f / FNgày dạng dài với giờ dạng ngắn / dàiCó
g / GNgày dạng ngắn với giờ dạng ngắn / dàiCó
MTháng và ngàyCó
YNăm và thángCó
oISO 8601 round-trip, 7 chữ số phần thập phân, múi giờKhông
sISO 8601 sắp xếp được, không phần thập phân, không múi giờKhông
uDạng sắp xếp được theo giờ quốc tế, kết thúc bằng ZKhông
rRFC 1123, cho HTTP headerKhông

o, s, u và r cho ra cùng một văn bản ở mọi culture, nên an toàn cho log, tên tệp và trao đổi dữ liệu. Lưu ý rằng với DateTime, u và r không chuyển giá trị sang UTC; chúng in nguyên giá trị và gắn nhãn UTC, nên hãy gọi ToUniversalTime() trước (hoặc dùng DateTime.UtcNow) nếu giá trị là giờ địa phương. (Với DateTimeOffset thì chúng có chuyển đổi.)

Culture thay đổi đầu ra

Định dạng chuẩn, tên tháng và tên thứ, cùng các dấu phân cách / và : đều đến từ culture. Truyền một culture làm đối số thứ hai cho ToString:

Đầu ra:

en-US  10/9/2026
en-GB  09/10/2026
de-DE  09.10.2026
fr-FR  09/10/2026
ja-JP  2026/10/09
Freitag, 9. Oktober 2026
vendredi 9 octobre 2026
09.10.2026
09/10/2026

Dữ liệu culture không cố định. .NET trên Linux và macOS đọc nó từ thư viện ICU cài trên hệ thống, và từ .NET 5, .NET trên Windows 10 trở lên cũng vậy (.NET Framework dùng dữ liệu NLS riêng của Windows), nên một mẫu có thể thay đổi đôi chút giữa các phiên bản và nền tảng: chẳng hạn các bản ICU gần đây đặt một khoảng trắng hẹp không ngắt dòng thay vì khoảng trắng thường trước "PM" trong định dạng giờ ngắn của Mỹ, và một số bản cho ngày ngắn tiếng Tây Ban Nha không có số 0 ở đầu. Đó thêm một lý do để không bao giờ phân tích văn bản đã được định dạng để hiển thị.

Từ đó có hai quy tắc. Với văn bản dành cho người đọc, hãy định dạng theo culture của họ (trên máy chủ, đó là culture lấy từ request, không phải của máy chủ) và ưu tiên định dạng chuẩn, để người đọc Đức thấy 09.10.2026 còn người đọc Mỹ thấy 10/9/2026. Với văn bản dành cho chương trình, hãy dùng CultureInfo.InvariantCulture và một mẫu rõ ràng như yyyy-MM-dd hoặc o. Một ngày được ghi bằng culture hiện tại rồi được phân tích trên máy khác là nguồn kinh điển của lỗi đảo ngày và tháng.

ISO 8601 và round-trip với "o"

Định dạng round-trip "o" ghi đủ mọi tick cùng thông tin múi giờ, nên phân tích lại văn bản sẽ cho đúng DateTime ban đầu, kể cả Kind của nó:

Đầu ra:

2026-10-09T18:30:07.0450000Z
2026-10-09T18:30:07.0450000
2026-10-09T20:30:07.0000000+02:00
True
Utc
2026-10-09T18:30:07Z
2026-10-09 20:30 +02:00

Hậu tố Z đánh dấu UTC; DateTime có Kind là Unspecified không có hậu tố; giờ địa phương hoặc DateTimeOffset có độ lệch của nó (+02:00). Phân tích với DateTimeStyles.RoundtripKind để giữ lại Kind. Các bộ tuần tự hóa JSON, cơ sở dữ liệu và Date của JavaScript đều đọc được định dạng này.

Định dạng TimeSpan

TimeSpan có bộ ký hiệu tùy chỉnh riêng, nhỏ hơn: d (ngày), hh, mm, ss và fff. Khác với DateTime, mọi ký tự nguyên văn, kể cả : và ., phải được escape bằng dấu gạch chéo ngược hoặc đặt trong dấu nháy:

Đầu ra:

1.03:25:09.1200000
1.03:25:09.1200000
03:25:09
1.03:25
25:09.120
27:25

hh trong định dạng TimeSpan là thành phần giờ (từ 0 đến 23), nên một khoảng thời gian 27 giờ được in ra là 03. Với tổng lớn hơn một ngày, hãy tính từ TotalHours như ở dòng cuối. elapsed.ToString("hh:mm") không có dấu gạch chéo ngược sẽ ném ra FormatException.

Lỗi thường gặp

  • mm cho tháng. "yyyy-mm-dd" in số phút ở giữa: 2026-30-09. Tháng là MM.
  • hh mà không có tt. "hh:mm" là đồng hồ 12 giờ không có AM hay PM, nên 06:30 không rõ là sáng hay tối. Dùng HH cho giờ dạng 24 giờ.
  • YYYY và DD. Không phải ký hiệu định dạng trong .NET; chúng được in nguyên văn. Dùng yyyy và dd.
  • / trong mẫu cho dữ liệu. Đó là dấu phân cách ngày của culture. Đặt nó trong dấu nháy hoặc dùng invariant culture.
  • ToString() mặc định trong log hoặc tệp. Định dạng phụ thuộc vào máy. Hãy truyền định dạng và culture.
  • Giờ địa phương bị gắn nhãn UTC. "u", "r" và 'Z' viết tay không chuyển đổi; hãy chuyển đổi trước.
  • Phân tích bằng mẫu khác với mẫu đã dùng để ghi. Giữ chuỗi định dạng cho dữ liệu trong một hằng số và dùng nó cho cả ToString và ParseExact.

Câu hỏi thường gặp

Làm sao định dạng DateTime thành yyyy-MM-dd trong C#?

date.ToString("yyyy-MM-dd") cho ra 2026-10-09. Trong chuỗi nội suy, viết $"{date:yyyy-MM-dd}". Thêm " HH:mm:ss" để có giờ theo dạng 24 giờ. Truyền CultureInfo.InvariantCulture làm đối số thứ hai khi văn bản dành cho tệp hoặc chương trình khác, để lịch, tên tháng và dấu phân cách không bao giờ phụ thuộc vào máy.

mm và MM trong định dạng ngày của C# khác nhau thế nào?

MM là tháng (từ 01 đến 12) và mm là phút (từ 00 đến 59). Định dạng phân biệt chữ hoa chữ thường, nên yyyy-mm-dd in số phút vào chỗ của tháng, một lỗi dễ bỏ sót khi bạn chỉ liếc qua một giá trị. Tương tự, HH là giờ dạng 24 giờ và hh là giờ dạng 12 giờ.

Làm sao định dạng DateTime theo ISO 8601 trong C#?

Dùng định dạng round-trip "o": DateTime.UtcNow.ToString("o") cho ra 2026-10-09T18:30:07.0450000Z, với bảy chữ số phần thập phân và Z cho UTC hoặc độ lệch múi giờ cho giờ địa phương. "s" cho dạng ngắn hơn, sắp xếp được, không có phần thập phân và múi giờ, còn "yyyy-MM-ddTHH:mm:ssZ" là một biến thể tùy chỉnh thường gặp.

Làm sao hiển thị AM và PM trong định dạng ngày của C#?

Dùng hh hoặc h cho đồng hồ 12 giờ và tt cho ký hiệu AM/PM: date.ToString("h:mm tt", CultureInfo.GetCultureInfo("en-US")) cho ra 6:30 PM. Ký hiệu này đến từ culture, và một số culture không có, nên hãy truyền culture tường minh khi bạn cần AM và PM.

Vì sao định dạng ngày của tôi hiện dấu chấm thay vì dấu gạch chéo?

Trong chuỗi định dạng, / không phải dấu gạch chéo nguyên văn mà là dấu phân cách ngày của culture, còn : là dấu phân cách giờ của culture. Trên máy cài tiếng Đức, dd/MM/yyyy in ra 09.10.2026. Đặt ký tự trong dấu nháy để ép nó, dd'/'MM'/'yyyy, hoặc định dạng với CultureInfo.InvariantCulture.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu