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
На півдорозі через цю обширну відповідь я задумався: чи це знову буде Джон? Так.
Гримаса відчаю

Як керувати тим же самим з Html.TextBoxFor (x => x.Date, "{0: MM / dd / yyyy}")?
VISHMAY

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 та HH.mm.ss у 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 SP1 та Windows Vista SP2 Повторне
Håkon Seljåsen

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.