VOV's world

DateTime C# issue

by vietfov on Jan.26, 2010, under IT

Việc xử lý với chuỗi thời gian thường hay gặp trong các chương trình đồng bộ, thống kê, schedule tasks. Vấn đề tưởng chừng như đơn giản khi sử dụng lớp DateTime, tuy nhiên lớp này lại tái hiện nguyên chuẩn thời gian trên hệ thống thời gian hiện tại của hệ điều hành.

Ví dụ với chuỗi ngày “25/02/2010″ ghi trong DB, khi cần đọc, hệ thống dùng chuẩn vi-VN sẽ thông báo đó là ngày 25 tháng 2, tuy nhiên với chuẩn en-US lại là ngày 2 tháng 25, dẫn đến System.FormatException. Sẽ là tai hoạ nếu đây là hệ thống backup hoặc tính lương nhân viên… Hoàn toàn khác với PHP, quy về một chuẩn format chung mặc định là Unix timestamp.

Vì vậy mới có trường hợp coder kêu đúng nhưng khách hàng lại báo sai.

Để khắc phục, các hàm Parse hoặc lưu DateTime trong DB hoặc khi nhập DateTime trong DateTimePicker không nên để mặc định mà cần dùng chung một chuẩn Format riêng (Custom). Nghĩa là khi sử dụng chuẩn vi-VN thì luôn lưu trữ, lấy thông tin theo kiểu vi-VN này (25/02/2010) và để dạng custom của nó là “dd/MM/yyyy”. Cho dù hệ thống hiện tại sử dụng định dạng gì đi nữa thì kết quả vẫn thể hiện đúng, nó vẫn hiểu đâu là ngày, đâu là tháng.

IFormatProvider culture = new CultureInfo(“vi-VN”, true);
string timeDayFormat = “dd/MM/yyyy”;
string timeHourFormat = “HH:mm:ss”;
string timeDayHourFormat = “dd/MM/yyyy HH:mm:ss”;

DateTime d = DateTime.ParseExact(“25/02/2010″, timeDateFormat, culture)
Console.WriteLine(d.toString());

// output
// Đối với hệ thống sử dụng en-US:
// 02/25/2010
// Đối với hệ thống sử dụng vi-VN:
// 25/02/2010

Tham khảo (trích msdn):

Định dạng Description Examples
“d” Ngày của tháng. Từ 1-31. 6/1/2009 1:45:30 PM -> 1

6/15/2009 1:45:30 PM -> 15

“dd” Ngày của tháng. Từ 01-31. 6/1/2009 1:45:30 PM -> 01

6/15/2009 1:45:30 PM -> 15

“ddd” Tên viết tắt của ngày trong Tuần. 6/15/2009 1:45:30 PM -> Mon (en-US)

6/15/2009 1:45:30 PM -> Пн (ru-RU)

6/15/2009 1:45:30 PM -> lun. (fr-FR)

“dddd” Tên đầy đủ của ngày trong Tuần. 6/15/2009 1:45:30 PM -> Monday (en-US)

6/15/2009 1:45:30 PM -> понедельник (ru-RU)

6/15/2009 1:45:30 PM -> lundi (fr-FR)

“f” Giá trị phần mười (1/10) của giây trong lớp thời gian. 6/15/2009 13:45:30.617 -> 6

6/15/2009 13:45:30.050 -> 0

“ff” Giá trị phần trăm (1/100) của giây trong lớp thời gian. 6/15/2009 13:45:30.617 -> 61

6/15/2009 13:45:30.005 -> 00

“fff” milliseconds 6/15/2009 13:45:30.617 -> 617

6/15/2009 13:45:30.0005 -> 000

“ffff” milliseconds (hàng ngàn) 6/15/2009 13:45:30.6175 -> 6175

6/15/2009 13:45:30.00005 -> 0000

“fffff” milliseconds (hàng chục ngàn) 6/15/2009 13:45:30.61754 -> 61754

6/15/2009 13:45:30.000005 -> 00000

“ffffff” milliseconds (hàng trăm ngàn) 6/15/2009 13:45:30.617542 -> 617542

6/15/2009 13:45:30.0000005 -> 000000

“fffffff” milliseconds (hàng triệu) 6/15/2009 13:45:30.6175425 -> 6175425

6/15/2009 13:45:30.0001150 -> 0001150

“F” Giá trị phần mười (1/10) của giây, khác 0 6/15/2009 13:45:30.617 -> 6

6/15/2009 13:45:30.050 -> (no output)

“FF” Giá trị phần trăm (1/100) của giây, khác 0 6/15/2009 13:45:30.617 -> 61

6/15/2009 13:45:30.005 -> (no output)

“FFF” Giá trị phần ngàn (1/1000) của giây, khác 0 6/15/2009 13:45:30.617 -> 617

6/15/2009 13:45:30.0005 -> (no output)

“FFFF” Giá trị phần chục ngàn (1/10000) của giây, khác 0 6/1/2009 13:45:30.5275 -> 5275

6/15/2009 13:45:30.00005 -> (no output)

“FFFFF” Giá trị phần trăm ngàn (1/100.000) của giây, khác 0 6/15/2009 13:45:30.61754 -> 61754

6/15/2009 13:45:30.000005 -> (no output)

“FFFFFF” Giá trị phần triệu (1/1.000.000) của giây, khác 0 6/15/2009 13:45:30.617542 -> 617542

6/15/2009 13:45:30.0000005 -> (no output)

“FFFFFFF” Giá trị phần chục triệu (1/10.000.000) của giây, khác 0 6/15/2009 13:45:30.6175425 -> 6175425

6/15/2009 13:45:30.0001150 -> 000115

“g”, “gg” Trước/ sau công nguyên 6/15/2009 1:45:30 PM -> A.D.
“h” Giờ. 1-12 6/15/2009 1:45:30 AM -> 1

6/15/2009 1:45:30 PM -> 1

“hh” Giờ. 00-12 6/15/2009 1:45:30 AM -> 01

6/15/2009 1:45:30 PM -> 01

“H” Giờ. 0-23 6/15/2009 1:45:30 AM -> 1

6/15/2009 1:45:30 PM -> 13

“HH” Giờ. 00-23 6/15/2009 1:45:30 AM -> 01

6/15/2009 1:45:30 PM -> 13

“K” Time zone information. 6/15/2009 1:45:30 PM, Kind Unspecified ->

6/15/2009 1:45:30 PM, Kind Utc -> Z

6/15/2009 1:45:30 PM, Kind Local -> -07:00

“m” Phút. 0-59 6/15/2009 1:09:30 AM -> 9

6/15/2009 1:09:30 PM -> 9

“mm” Phút. 00-59 6/15/2009 1:09:30 AM -> 09

6/15/2009 1:09:30 PM -> 09

“M” Tháng. 1-12 6/15/2009 1:45:30 PM -> 6
“MM” Tháng. 01-12 6/15/2009 1:45:30 PM -> 06
“MMM” Tên viết tắt của Tháng. 6/15/2009 1:45:30 PM -> Jun (en-US)

6/15/2009 1:45:30 PM -> juin (fr-FR)

6/15/2009 1:45:30 PM -> Jun (zu-ZA)

“MMMM” Tên đầy đủ của Tháng. 6/15/2009 1:45:30 PM -> June (en-US)

6/15/2009 1:45:30 PM -> juni (da-DK)

6/15/2009 1:45:30 PM -> uJuni (zu-ZA)

“s” Giây. 0-59 6/15/2009 1:45:09 PM -> 9
“ss” Giây. 00-59 6/15/2009 1:45:09 PM -> 09
“t” Chữ cái đầu tiên của định danh AM/PM 6/15/2009 1:45:30 PM -> P (en-US)

6/15/2009 1:45:30 PM -> 午 (ja-JP)

6/15/2009 1:45:30 PM -> (fr-FR)

“tt” AM/PM 6/15/2009 1:45:30 PM -> PM (en-US)

6/15/2009 1:45:30 PM -> 午後 (ja-JP)

6/15/2009 1:45:30 PM -> (fr-FR)

“y” Năm. 0-99 1/1/0001 12:00:00 AM -> 1

1/1/0900 12:00:00 AM -> 0

1/1/1900 12:00:00 AM -> 0

6/15/2009 1:45:30 PM -> 9

“yy” Năm. 00-99 1/1/0001 12:00:00 AM -> 01

1/1/0900 12:00:00 AM -> 00

1/1/1900 12:00:00 AM -> 00

6/15/2009 1:45:30 PM -> 09

“yyy” Năm. Tối thiểu là 3 ký tự. 1/1/0001 12:00:00 AM -> 001

1/1/0900 12:00:00 AM -> 900

1/1/1900 12:00:00 AM -> 1900

6/15/2009 1:45:30 PM -> 2009

“yyyy” Năm. 4 ký tự. 1/1/0001 12:00:00 AM -> 0001

1/1/0900 12:00:00 AM -> 0900

1/1/1900 12:00:00 AM -> 1900

6/15/2009 1:45:30 PM -> 2009

“yyyyy” Năm. 5 ký tự. 1/1/0001 12:00:00 AM -> 00001

6/15/2009 1:45:30 PM -> 02009

“z” Giờ lệch với giờ UTC. 6/15/2009 1:45:30 PM -07:00 -> -7
“zz” Giờ lệch với giờ UTC. Có số 0 đứng đầu. 6/15/2009 1:45:30 PM -07:00 -> -07
“zzz” Giờ:Phút lệch với giờ UTC. Có số 0 đứng đầu. 6/15/2009 1:45:30 PM -07:00 -> -07:00
“:” Ký tự tách giờ. 6/15/2009 1:45:30 PM -> : (en-US)

6/15/2009 1:45:30 PM -> . (it-IT)

6/15/2009 1:45:30 PM -> : (ja-JP)

“/” Ký tự tách ngày. 6/15/2009 1:45:30 PM -> / (en-US)

6/15/2009 1:45:30 PM -> – (ar-DZ)

6/15/2009 1:45:30 PM -> . (tr-TR)

“string”

‘string’

Chuỗi tách giờ. 6/15/2009 1:45:30 PM (“arr:” h:m t) -> arr: 1:45 P

6/15/2009 1:45:30 PM (‘arr:’ h:m t) -> arr: 1:45 P

% Xác định ký tự với kiểu Custom 6/15/2009 1:45:30 PM (%h) -> 1
\ Ký tự bồi. 6/15/2009 1:45:30 PM (h \h) -> 1 h
Any other character Ký tự luôn không đổi sau khi định dạng. 6/15/2009 1:45:30 AM (arr hh:mm t) -> arr 01:45 A

2 Comments for this entry

  • huong

    Cai nay dau co duoc ha ban, minh dung ca vn va us deu ra dinh dang mm/dd/yyyy

  • Anonymous

    Khi bạn xuất ra hệ thống với tham số mặc định thì đương nhiên sẽ xuất theo chuẩn cài đặt trên máy tính của bạn (mm/dd/yyyy), qua máy tính en-US thì sẽ hiển thị dạng en-US.

    Cái này để đồng bộ việc read/write một chuỗi thời gian vào một nơi nào đó.

    viet.

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...