DateTime.ToString («MM / dd / yyyy HH: mm: ss.fff») привел к примерно «14.09.2013 07.20.31.371».


131

У меня есть приложение WP8, которое отправляет текущее время в веб-службу.

Я получаю строку даты и времени, вызывая

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

Для большинства пользователей он отлично работает и дает мне правильную строку, например "09/10/2013 04:04:31.415". Но для некоторых пользователей полученная строка выглядит примерно так "09/14/2013 07.20.31.371", что вызывает проблемы в моем веб-сервисе.

Это потому, что проблема с культурным форматом? Как я могу убедиться, что строка результата разделена двоеточием вместо точки?


2
единственная разница - двоеточие против точки.
Эльдорадо

См. Образцы .Net Standard 2
Sina Lotfi

Ответы:


244

Это потому, что проблема с культурным форматом?

Да. Ваш пользователь должен принадлежать к культуре, где разделителем времени является точка. И «:», и «/» интерпретируются с учетом языка и региональных параметров в настраиваемых форматах даты и времени .

Как я могу убедиться, что строка результата разделена двоеточием вместо точки?

Предлагаю уточнить CultureInfo.InvariantCulture:

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

В качестве альтернативы вы можете просто указать разделители времени и даты:

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

... но это даст вам «интересные» результаты, которых вы, вероятно, не ожидаете, если вы заставите пользователей работать в культуре, где календарная система по умолчанию не является григорианским календарем. Например, возьмите следующий код:

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"));
    }
} 

Это дает результат (18 сентября 2013 г.):

11/12/1434 15:04:31.750

Полагаю, ваш веб-сервис будет этим удивлен!

На самом деле я бы предложил не только использовать инвариантную культуру, но и перейти на формат даты ISO-8601:

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

Это более распространенный во всем мире формат - он также сортируется и делает очевидным порядок месяца и дня. (В то время как 06.07.2013 можно интерпретировать как 7 июня или 6 июля в зависимости от культуры читателя.)


спасибо Джон. Я думал, что строка результата будет точно такой же, как и строка формата. Я попробую ваше предложение.
Эльдорадо

3
Только одно небольшое соображение. При загрузке объекта CultureInfo из определенного кода я всегда предлагаю установить для useUserOverrideпараметра значение false, в противном случае некоторые пользовательские настройки могут переопределить настройки культуры. Например в вашем случае предлагаю использовать новый CultureInfo("ar-SA", false).
Давиде Икарди

@DavideIcardi: Интересно, спасибо - хотя в данном случае целью использования Саудовской Аравии было конкретно сказать, почему использование инвариантной культуры, вероятно, правильно. Но учтите это в будущих публикациях.
Джон Скит,

7
На полпути к этому обширному ответу я начал задаваться вопросом: будет ли это снова Джон? Ага.
Grimace of Despair

Как сделать то же самое с Html.TextBoxFor (x => x.Date, "{0: MM / dd / yyyy}")?
VISHMAY 01

9

:имеет особое значение: это разделитель времени. ( Строки настраиваемого формата даты и времени ).

Используйте, \чтобы избежать этого:

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

Или используйте CultureInfo.InvariantCulture:

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

Я бы посоветовал использовать второй, потому что он /тоже имеет особое значение (это разделитель даты ), так что у вас могут быть проблемы и с этим.


2
Проблема заключается не только в разделителе даты - см. Мой ответ, чтобы увидеть пример того, как культура влияет на фактические числа ...
Джон Скит

1
\ не ускользнет!
Шериф Марзук

8

Вы можете использовать InvariantCulture, потому что ваш пользователь должен принадлежать к культуре, в которой используется точка вместо двоеточия:

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

7

Недавно я столкнулся с этой проблемой с Windows 10 с другого направления и нашел ответ от @JonSkeet очень полезным в решении моей проблемы.

Я также провел несколько дополнительных исследований с помощью тестовой формы и обнаружил, что когда текущая культура была установлена ​​на "no"или "nb-NO"во время выполнения ( Thread.CurrentThread.CurrentCulture = new CultureInfo("no");), вызов ToString ("yyyy-MM-dd HH: mm: ss") реагировал по-разному в Windows 7 и Windows 10. Он вернул то, что я ожидал в Windows 7 и ЧЧ.мм.сс в Windows 10!

Я думаю, это немного страшно! Поскольку я считал, что культура была культурой по крайней мере в любой версии Windows.


Мне было бы очень любопытно узнать, что на самом деле вызывает это.
Лаури Пелтонен

2
Это было признано и исправлено как ошибка локализации Windows 10. Таким образом, обновление Windows на клиентском компьютере устранит проблему. Более подробная информация доступна в этом сообщении в блоге: heikniemi.net/hardcoded/2015/08/…
Håkon Seljåsen

Блог Йоуни Хейкниеми, на который я ссылался выше, похоже, не работает. Соответствующие обновления Windows, в которых были устранены проблемы, перечислены здесь: 2015-10-09: KB3093266 - Windows 10 KB3088956 - Windows Server 2012 R2 и Windows 8.1 KB3088955 - Windows Server 2012 и Windows 8 KB3088957 - Windows 7 SP1, Windows Server 2008 SP2 , Windows Server 2008 R2 с пакетом обновления 1 (SP1) и Windows Vista с пакетом обновления 2 (SP2) Попытка снова установить ссылку на блог, на этот раз через archive.org: web.archive.org/web/20161030193739/http://www.heikniemi.net/…
Хокон Селйосен

4

Вы можете использовать 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"

0

Преобразовать дату в строку

Использовать пространство имен

using System.Globalization;

Код

string date = DateTime.ParseExact(datetext.Text, "dd-MM-yyyy", CultureInfo.InstalledUICulture).ToString("yyyy-MM-dd");

Это не способ преобразования даты в строку. Парсинг происходит наоборот!
Винсент Ванкалберг
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.