2010-07-30 9 views
5

Considerate questo codice (prestuffed con un esempio):Perché questa particolare stringa di formato TimeSpan ha smesso di funzionare in .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)); 

Questo è rappresentativo di un pezzo di codice che ho avuto a lavorare dal .NET 1.1, almeno.

ha funzionato bene in 1.1 a 3.5 con il seguente output (per questi ingressi dummied up):

30.00:00:28.3580246 

Ma ora sto vedendo che muore in .NET 4 con il messaggio di errore:

Input string was not in a correct format.

Quindi è come se .NET 4 abbia improvvisamente deciso che questo formato non piace per le differenze di orario. Modifica della linea, ad esempio

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

ha lo stesso effetto.

Ora la cosa che ho notato è che se faccio solo il default .ToString() ottengo lo stesso risultato. Credo che il processo di riflessione fosse che si trattava di una polizza assicurativa contro il formato predefinito che cambia in una versione futura. Ma ora non sembra che sia anche un'opzione.

Qualcuno sa perché questo è cambiato e se sto facendo qualcosa di sbagliato o se c'è un modo migliore pratiche per fare quello che sto cercando di realizzare?

+0

In che cultura si trova? –

+0

La mia cultura locale è: en-US –

risposta

6

C'è un configuration switch per ripristinare il vecchio comportamento di TimeSpan.

+1

Quindi in pratica quella stringa di formato non ha fatto nulla per tutto questo tempo. Eccezionale. Grazie. –

+0

@Schnapple Esattamente. In .NET 3.5 e precedenti, la struttura 'TimeSpan' non era' IFormattable'. Quando 'string.Format' e i metodi correlati vedono qualcosa come' {0: something} 'e l'argomento fornito non è' IFormattable', non hanno nessun posto dove mettere quella stringa di formato, e lo scartano semplicemente. Questo è quello che è successo nel tuo codice fino a quando è arrivato .NET 4.0. –

0

Ho incollato il vostro pezzo di codice e sembra essere un problema culturale:

con .NET 2 un FormatException è gettato troppo

Se ho specificato la cultura noi (la cultura è it-IT per impostazione predefinita), il codice funziona:

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

Potete anche specificato un cultura invarianti di ignorare la cultura

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

Penso che tu abbia in mente qualcosa con la cultura ma, ma non sono le righe DateTime che mi stanno dando problemi, è la stringa di formato TimeSpan. Anche se si specifica la cultura in TimeSpan ToString e entrambi i metodi DateTime.Parse, sto ancora ottenendo lo stesso. –

3

Un'alternativa all'interruttore di configurazione è una modifica del formato compatibile con le versioni precedenti.

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

Questa soluzione è il dettaglio here.

+0

Questo lo ha risolto per me :) –

1

Infatti, la stringa di formato composito che hai utilizzato nel codice non ha avuto alcun effetto a tutti, perché TimeSpannon supporto stringhe di formato personalizzato (NET < 4.0).

, ad esempio TimeSpan sarebbe sempre stato formattato come 30.00:00:28.3580246 indipendentemente dalla stringa di formato.

Da MSDN:

Nelle versioni precedenti di .NET Framework, la struttura TimeSpan ha non implementa IFormattable e non ha sostenuto le stringhe di formato.

Tuttavia, molti sviluppatori erroneamente assume che TimeSpan fatto supporto un insieme di stringhe di formato e usato nella formattazione composito operazioni con metodi come String.Format. In genere, se un tipo implementa IFormattable e supporta le stringhe di formato, le chiamate ai metodi di formattazione con stringhe di formato non supportate solitamente generano un valore di FormatException . Tuttavia, poiché TimeSpan non ha implementato IFormattable, il runtime ha ignorato la stringa di formato e ha invece chiamato il metodo TimeSpan.ToString(). Ciò significa che, sebbene le stringhe del formato non avessero effetto sull'operazione di formattazione, la loro presenza non ha provocato in FormatException.

1

Come indicato da Mitch grano e Saeb Amini in theiranswers, TimeSpan non implementa IFormattable prima di .NET 4.0. Di conseguenza, le stringhe di formato hanno senza effetto sull'output TimeSpan.ToString() poiché sono state ignorate.

Tuttavia, poiché TimeSpan non ha attuato IFormattable, il runtime ignorato la stringa di formato e invece chiamato il metodo TimeSpan.ToString. Ciò significa che, sebbene le stringhe di formato non abbiano avuto alcun effetto sull'operazione di formattazione, la loro presenza non ha generato un FormatException.

Source

Detto questo, fi che si desidera formattare un valore TimeSpan su tutte le versioni di .NET framework, è molto meglio per convertire il valore TimeSpan-DateTime e poi formato che risulta come mostrato di seguito :

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 
Problemi correlati