2010-07-30 41 views
5

xem xét mã này (prestuffed với một ví dụ):Tại sao chuỗi định dạng TimeSpan cụ thể này ngừng hoạt động trong .NET 4?

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM"); 
DateTime dt2 = DateTime.Parse("6/30/2010 9:33:00.7654321 AM"); 

TimeSpan ts = dt1 - dt2; 

Console.WriteLine(string.Format("{0:d.hh:mm:ss.ff}", ts)); 

Đây là đại diện của một đoạn mã mà tôi đã đã làm việc kể từ NET 1.1 ít nhất.

Nó hoạt động tốt trong 1.1 đến 3.5 với kết quả như sau (đối với những đóng góp dummied lên):

30.00:00:28.3580246 

Nhưng bây giờ tôi thấy rằng nó chết trong .NET 4 với thông báo lỗi:

Input string was not in a correct format.

Vì vậy, như thể .NET 4 đã đột nhiên quyết định không thích định dạng này cho sự khác biệt về thời gian. Thay đổi dòng, giả sử

Console.WriteLine(string.Format("{0}", ts.ToString("d.hh:mm:ss.ff"))); 

có cùng tác dụng.

Bây giờ điều tôi đã nhận thấy là nếu tôi chỉ làm mặc định .ToString() tôi nhận được cùng một đầu ra. Tôi tin rằng quá trình suy nghĩ là đây là một chính sách bảo hiểm chống lại định dạng mặc định thay đổi trong một phiên bản tương lai. Nhưng bây giờ nó không giống như đó thậm chí là một lựa chọn.

Có ai biết tại sao điều này thay đổi và nếu tôi đang làm điều gì đó sai hoặc nếu có cách thực hành tốt nhất để làm những gì tôi đang cố gắng hoàn thành?

+0

Văn hóa này thuộc loại nào? –

+0

Văn hóa địa phương của tôi là: en-US –

Trả lời

6

Có một số configuration switch để khôi phục hành vi cũ của TimeSpan.

+1

Vì vậy, về cơ bản chuỗi định dạng đã không làm gì cả. Nổi bật. Cảm ơn. –

+0

@Schnapple Chính xác. Trong .NET 3.5 trở về trước, cấu trúc 'TimeSpan' không phải là' IFormattable'. Khi 'string.Format' và các phương thức liên quan thấy một cái gì đó như' {0: something} 'và đối số được cung cấp không phải là' IFormattable', chúng không có nơi nào để đặt chuỗi định dạng đó, và chúng chỉ loại bỏ nó. Đó là những gì đã xảy ra trong mã của bạn cho đến khi .NET 4.0 đến. –

0

Tôi đã dán miếng lại mã và nó có vẻ là một vấn đề văn hóa:

với NET 2 một FormatException được ném quá

Nếu tôi đã chỉ định các nền văn hóa chúng ta (văn hóa là fr-FR theo mặc định), mã hoạt động:

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM", CultureInfo.GetCultureInfo("en-US")); 

Bạn cũng có thể quy định một nền văn hóa bất biến để bỏ qua văn hóa

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM", CultureInfo.InvariantCulture); 
+1

Tôi nghĩ bạn đang ở một thứ gì đó với văn hóa nhưng, nhưng không phải là các dòng DateTime đang cho tôi phù hợp, đó là chuỗi định dạng TimeSpan. Ngay cả khi tôi chỉ định văn hóa trong TimeSpan ToString và cả hai phương thức DateTime.Parse, tôi vẫn nhận được như vậy. –

3

Một thay thế cho công tắc cấu hình là thay đổi định dạng tương thích với các phiên bản trước.

Console.WriteLine(string.Format("{0:hh\\:mm\\:ss.ff}", ts)); 

Giải pháp này là chi tiết here.

+0

Điều này cố định nó cho tôi :) –

1

Trong thực tế, chuỗi định dạng hỗn hợp bạn đã sử dụng trong mã của bạn không có bất kỳ tác dụng ở tất cả các, vì TimeSpankhông hỗ trợ định dạng tùy chỉnh dây (NET < 4.0).

tức là TimeSpan của bạn sẽ luôn được định dạng như 30.00:00:28.3580246 bất kể chuỗi định dạng.

Từ MSDN:

Trong các phiên bản trước của .NET Framework, cấu trúc TimeSpan đã không thực hiện IFormattable và không hỗ trợ định dạng chuỗi.

Tuy nhiên, nhiều nhà phát triển nhầm lẫn cho rằng TimeSpan đã hỗ trợ một tập hợp các định dạng chuỗi và sử dụng chúng trong định dạng composit hoạt động với các phương pháp như String.Format. Thông thường, nếu một loại triển khai IFormattable và hỗ trợ các chuỗi định dạng, hãy gọi tới các phương pháp định dạng bằng các chuỗi định dạng không được hỗ trợ thường ném một FormatException. Tuy nhiên, vì TimeSpan không thực hiện IFormattable, thời gian chạy bỏ qua chuỗi định dạng và thay vào đó được gọi là phương thức TimeSpan.ToString(). Điều này có nghĩa là, mặc dù định dạng chuỗi không ảnh hưởng đến hoạt động định dạng, sự hiện diện của chúng đã làm không dẫn đến việc định dạng.

1

Như đã nêu bởi Mitch mì và Saeb Amini trong theiranswers, TimeSpan không thực hiện IFormattable trước .NET 4.0. Do đó, các chuỗi định dạng có không có hiệu lực trên đầu ra TimeSpan.ToString() vì chúng bị bỏ qua.

Tuy nhiên, do TimeSpan đã không thực hiện IFormattable, runtime bỏ chuỗi định dạng và thay vào đó gọi là phương pháp TimeSpan.ToString. Điều này có nghĩa rằng, mặc dù các chuỗi định dạng không có hiệu lực đối với hoạt động định dạng, sự hiện diện của chúng không dẫn đến một FormatException.

Source

Điều đó nói rằng, fi mà bạn mong muốn để định dạng một giá trị TimeSpan trên tất cả các phiên bản của .NET framework, nó là tốt hơn để chuyển đổi giá trị TimeSpan-DateTime và sau đó định dạng mà kết quả như hình dưới đây :

DateTime dt1 = DateTime.Parse("7/30/2010 9:33:29.1234567 AM"); 
DateTime dt2 = DateTime.Parse("6/30/2010 9:33:00.7654321 AM"); 

TimeSpan ts = dt1 - dt2; 

Console.WriteLine(String.Format("{0:d.hh:mm:ss.ff}", new DateTime(ts.Ticks))) 
// prints 30.00:00:28.36 
Các vấn đề liên quan