DateTime.ToString („MM / dd / yyyy HH: mm: ss.fff”) zwróciło wynik na przykład „09/14/2013 07.20.31.371”

133

Mam aplikację WP8, która wyśle ​​aktualny czas do usługi internetowej.

Otrzymuję ciąg daty i godziny, dzwoniąc

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff")

Dla większości użytkowników działa świetnie i daje mi prawidłowy ciąg, taki jak "09/10/2013 04:04:31.415". Ale dla niektórych użytkowników wynikowy ciąg jest czymś w rodzaju "09/14/2013 07.20.31.371", co powoduje problem w mojej usłudze internetowej.

Czy to z powodu jakiegoś problemu z formatem kultury? Jak mogę się upewnić, że ciąg wynikowy jest oddzielony dwukropkiem, a nie kropką?

Eldorado
źródło
2
jedyną różnicą jest dwukropek vs kropka.
Eldorado
Zobacz próbki .Net Standard 2
Sina Lotfi,

Odpowiedzi:

248

Czy to z powodu jakiegoś problemu z formatem kultury?

Tak. Twój użytkownik musi znajdować się w kulturze, w której separatorem czasu jest kropka. Zarówno „:”, jak i „/” są interpretowane z uwzględnieniem kultury w niestandardowych formatach daty i godziny .

Jak mogę się upewnić, że ciąg wynikowy jest oddzielony dwukropkiem, a nie kropką?

Proponuję określić CultureInfo.InvariantCulture:

string text = dateTime.ToString("MM/dd/yyyy HH:mm:ss.fff",
                                CultureInfo.InvariantCulture);

Alternatywnie, to mógłby tylko zacytować separatory czasu i daty:

string text = dateTime.ToString("MM'/'dd'/'yyyy HH':'mm':'ss.fff");

... ale to da Ci „interesujące” wyniki, których prawdopodobnie nie spodziewasz się, jeśli uzyskasz użytkowników działających w kulturze, w której domyślny system kalendarza nie jest kalendarzem gregoriańskim. Na przykład weź następujący kod:

using System;
using System.Globalization;
using System.Threading;

class Test
{
    static void Main()        
    {
        DateTime now = DateTime.Now;
        CultureInfo culture = new CultureInfo("ar-SA"); // Saudi Arabia
        Thread.CurrentThread.CurrentCulture = culture;
        Console.WriteLine(now.ToString("yyyy-MM-ddTHH:mm:ss.fff"));
    }
} 

To produkuje (18 września 2013):

11/12/1434 15:04:31.750

Domyślam się, że Twoja usługa internetowa byłaby tym zaskoczona!

Właściwie sugerowałbym nie tylko użycie niezmiennej kultury, ale także zmianę na format daty ISO-8601:

string text = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

Jest to format bardziej akceptowany na całym świecie - można go również sortować, a porządek miesiąca i dnia jest oczywisty. (Natomiast 06/07/2013 można interpretować jako 7 czerwca lub 6 lipca, w zależności od kultury czytelnika).

Jon Skeet
źródło
dzięki Jon. Pomyślałem, że ciąg wynikowy będzie dokładnie taki sam, jak ciąg formatu. Spróbuję twojej sugestii.
Eldorado
3
Tylko jedna drobna uwaga. Podczas ładowania obiektu CultureInfo z określonego kodu zawsze sugeruję ustawienie useUserOverrideparametru na false, w przeciwnym razie niektóre ustawienia użytkownika mogą zastąpić ustawienia kultury. Na przykład w twoim przypadku proponuję użyć nowego CultureInfo("ar-SA", false).
Davide Icardi
@DavideIcardi: Ciekawe, dziękuję - chociaż w tym przypadku celem użycia Arabii Saudyjskiej było w szczególności wyjaśnienie, dlaczego używanie niezmiennej kultury jest prawdopodobnie właściwe. Pamiętaj o tym jednak w przyszłych postach.
Jon Skeet,
7
W połowie tej obszernej odpowiedzi zacząłem się zastanawiać: czy to znowu Jon? Tak.
Grimace of Despair
Jak zarządzać tym samym z Html.TextBoxFor (x => x.Date, „{0: MM / dd / rrrr}”)?
VISHMAY
10

:ma specjalne znaczenie: jest to separator czasu. ( Ciągi niestandardowego formatu daty i godziny ).

Użyj, \aby uciec:

DateTime.ToString(@"MM/dd/yyyy HH\:mm\:ss.fff")

Lub użyj CultureInfo.InvariantCulture:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture)

Proponuję wybrać drugą, ponieważ /ma również specjalne znaczenie (jest to Separator daty ), więc możesz mieć z tym problemy.

MarcinJuraszek
źródło
2
Problemem jest nie tylko separator daty - zobacz moją odpowiedź na przykład kultury wpływającej również na rzeczywiste liczby ...
Jon Skeet
1
\ nie ucieknie!
Shereef Marzouk
8

Możesz użyć InvariantCulture, ponieważ Twój użytkownik musi znajdować się w kulturze, która używa kropki zamiast dwukropka:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
Jon La Marr
źródło
7

Ostatnio natknąłem się na ten problem z Windows 10 z innego kierunku i znalazłem odpowiedź od @JonSkeet bardzo pomocną w rozwiązaniu mojego problemu.

Przeprowadziłem również dalsze badania z formularzem testowym i odkryłem, że gdy bieżąca kultura została ustawiona na "no"lub "nb-NO"w czasie wykonywania ( Thread.CurrentThread.CurrentCulture = new CultureInfo("no");), wywołanie ToString („rrrr-MM-dd HH: mm: ss”) odpowiadało inaczej w systemie Windows 7 i Windows 10. Zwrócił to, czego oczekiwałem w Windows 7 i HH.mm.ss w Windows 10!

Myślę, że to trochę przerażające! Ponieważ wierzyłem, że kultura jest kulturą przynajmniej w dowolnej wersji systemu Windows.

Håkon Seljåsen
źródło
Byłbym bardzo ciekawy, co tak naprawdę to powoduje.
Lauri Peltonen
2
Został rozpoznany i naprawiony jako błąd lokalizacji systemu Windows 10. Tak więc aktualizacja systemu Windows na komputerze klienckim rozwiąże problem. Więcej szczegółów można znaleźć w tym poście na blogu: heikniemi.net/hardcoded/2015/08/…
Håkon Seljåsen
Blog Jouniego Heikniemi, do którego zamieściłem link powyżej, wydaje się być uszkodzony. Odpowiednie aktualizacje systemu Windows, w których zostały rozwiązane problemy, zostały tam wymienione: 2015-10-09: KB3093266 - Windows 10 KB3088956 - Windows Server 2012 R2 i Windows 8.1 KB3088955 - Windows Server 2012 i Windows 8 KB3088957 - Windows 7 SP1, Windows Server 2008 SP2 , Windows Server 2008 R2 z dodatkiem SP1 i Windows Vista z dodatkiem SP2 Ponownie próbuję
Håkon Seljåsen
4

Możesz użyć String.Format:

DateTime d = DateTime.Now;
string str = String.Format("{0:00}/{1:00}/{2:0000} {3:00}:{4:00}:{5:00}.{6:000}", d.Month, d.Day, d.Year, d.Hour, d.Minute, d.Second, d.Millisecond);
// I got this result: "02/23/2015 16:42:38.234"
Cosmin
źródło
0

Konwertuj datę na ciąg

Użyj przestrzeni nazw

using System.Globalization;

Kod

string date = DateTime.ParseExact(datetext.Text, "dd-MM-yyyy", CultureInfo.InstalledUICulture).ToString("yyyy-MM-dd");
Hafsal
źródło
To nie jest sposób na konwersję daty na ciąg. Parsowanie jest odwrotne!
Vincent Vancalbergh,