2010-07-30 12 views
5

Rozważmy następujący kod (prestuffed z przykładu):Dlaczego ten konkretny ciąg formatu TimeSpan przestał działać w .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)); 

ten jest reprezentatywny kawałek kodu, który miałem pracy od .NET 1.1 przynajmniej.

to działało dobrze w 1.1 do 3.5 z następującym wyjścia (dla tych dummied się wejść):

30.00:00:28.3580246 

Ale teraz widzę, że umiera w .NET 4 z komunikatem o błędzie:

Input string was not in a correct format.

To tak, jakby .NET 4 nagle zdecydował, że ten format nie podoba się w przypadku różnic czasowych. Zmiana linii na, na przykład:

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

ma taki sam efekt.

Teraz zauważyłem, że jeśli po prostu zrobię domyślny .ToString(), otrzymam ten sam wynik. Uważam, że proces myślenia polegał na tym, że była to polisa ubezpieczeniowa od domyślnego formatu zmieniającego się w przyszłej wersji. Ale teraz nie wygląda na to, że to nawet opcja.

Czy ktoś wie, dlaczego to się zmieniło i czy robię coś nie tak, czy istnieje najlepszy sposób na zrobienie tego, co próbuję osiągnąć?

+0

W której to jest kulturze? –

+0

Moja lokalna kultura to: en-US –

Odpowiedz

6

Istnieje configuration switch w celu przywrócenia starego zachowania TimeSpan.

+1

Tak więc ten ciąg formatów nic nie robił przez cały ten czas. Wybitny. Dzięki. –

+0

@ Chaptat Dokładnie. W .NET 3.5 i wcześniejszych, struktura 'TimeSpan' nie była' IFormattable'. Kiedy 'string.Format' i podobne metody zobacz coś jak' {0: something} 'i podany argument nie jest" IFormattable ", nie mają gdzie umieścić ten ciąg formatu, a oni po prostu go odrzucają. Tak właśnie stało się w twoim kodzie, dopóki nie pojawi się .NET 4.0. –

0

mam wklejony swój kawałek kodu i wydaje się być problemem kultura:

z .NET 2 FormatException jest wyrzucany zbyt

Gdybym określony kulturę nas (kultura fr-FR domyślnie), kod działa:

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

można również określić niezmiennikiem kulturę ignorować kulturę

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

Wydaje mi się, że interesuje cię kultura, ale to nie linie DateTime dają mi pasowania, to ciąg w formacie TimeSpan. Nawet jeśli określę kulturę w TimeScale ToString i obie metody DateTime.Parse, nadal otrzymuję to samo. –

3

Alternatywą dla przełącznika konfiguracji jest zmiana formatu zgodna z poprzednimi wersjami. To jest detal here.

+0

Naprawiono to dla mnie :) –

1

W rzeczywistości, format string kompozyt używałeś w kodzie nie mają żadnego wpływu na wszystkich, ponieważ TimeSpannie wsparcia ciągi format niestandardowy (.NET < 4,0).

tj. Twój TimeSpan zawsze byłby sformatowany jak 30.00:00:28.3580246, niezależnie od łańcucha formatu.

Od MSDN:

W poprzednich wersjach .NET Framework, struktura TimeSpan nie nie wdrożyć IFormattable i nie wspiera ciągi formatu.

Jednak wielu deweloperów błędnie zakłada, że ​​TimeSpan zrobił wsparcia zestaw formatów ciągów i stosować je w formatowaniu kompozytowego operacje z metod, takich jak String.Format. Zazwyczaj, jeśli typ implementuje IFormattable i obsługuje ciągi formatów, wywołania metod formatowania z nieobsługiwanymi ciągami formatów zwykle powodują wyjątek FormatException. Ponieważ jednak TimeSpan nie wdrożyłoIFormattable, środowisko wykonawcze zignorowało ciąg formatu i zamiast tego wywołało nazwę metody TimeSpan.ToString(). Oznacza to, że chociaż ciągi w formacie nie miały wpływu na operację formatowania, ich obecność nie spowodowała wyjątku FormatException.

1

Jak wskazano przez Mitch Wheat i Saeb Amini w theiranswers, TimeSpan nie implementuje IFormattable przed .NET 4.0. W związku z tym ciągi formatu mają bez skutku na wyjściu TimeSpan.ToString(), ponieważ zostały zignorowane.

Jednak ponieważ TimeSpan nie wdrożył IFormattable, runtime zignorował ciąg formatu i zamiast nazywa się metodą TimeSpan.ToString. Oznacza to, że chociaż ciągi formatujące nie miały wpływu na operację formatowania, ich obecność nie spowodowała wyjątku FormatException.

Source

Powiedział, że fi chec sformatować wartość TimeSpan we wszystkich wersjach systemu .NET Framework, jest o wiele lepiej do konwersji wartości TimeSpan do DateTime a następnie format, który prowadzić jak pokazano poniżej :

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