Denis Gladkikh
Russian   |  English

Коварный символ ‘/’ в custom формате даты

Вопрос, какую директорию создаст этот код?

string sole = DateTime.Today.ToString("yyyy/MM/dd");
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, sole);
if (!Directory.Exists(path))
    Directory.CreateDirectory(path);

Вчера для меня было шоком, что, вроде, логично ожидать директорию вроде “…/2010/08/29”,  а я получил “…/2010.08.29”. Запускаем этот код:

CultureInfo[] cultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures);
 
foreach (var cultureInfo in cultureInfos)
{
    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;
 
    string sole = DateTime.Today.ToString("yyyy/MM/dd");
    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, sole);
 
    Console.WriteLine(path);
}
 
Console.ReadKey();

И смотрим:

Console

В общем,  раньше не встречался с этой фичей, а оказывается - это специальный символ в custom формате, который подставляется на значение из DateTimeFormatInfo.DateSeparator (такой же есть и для времени). Как хорошо, что у нас разделитель точка, а вот другие страны мучаются и не понимают, почему их формат “dd/MM/yyyy” не работает, во время я осознал проблему и подсказал об этой фиче.

Все мелочи не запомнишь, и многое просто проскальзывает, .NET расширяется с каждым годом, и даже базовые вещи уже не все помнишь. Вы, кстати, знали об этой фиче? Были ли подобные неожиданные встречи?


Вас также может заинтересовать

rss twitter

Комментарии (14)

force ( ) #
avatar
Попался :) Правильно писать '/' и все другие буквы лучше тоже оборачивать в одинарные кавычки, мало ли что.
Вообще, хочу написать статью про то, как испоганить окружение на своём рабочем компе, чтобы такие вещи ловились автоматом, но всё руки не доходят.
Сергей Попов ( ) #
avatar
Ай-ай-ай, ToString() без явного Culture Provider в данном случае – это плохой стиль! ;-)
Сергей Попов ( ) #
avatar
P.S. А я знал, я когда-то очень давно обжегся на custom format strings, и после этого всегда читаю их спецификацию ;-)
Denis Gladkikh ( ) #
avatar
force, все таки лучший вариант будет использовать в этом случае Path:

DateTime d = DateTime.Today;
Path.Combine(d.ToString("yyyy"), d.ToString("MM"), d.ToString("dd"));

Либо явно использовать Path.PathSeparator.

Сергей Попов, поддерживаю :)
force ( ) #
avatar
Denis Gladkikh, Лучше явно, да PathSeparator, а если обычный обратный слеш то разницы нет
Сергей Антипов ( ) #
avatar
Почти везде использую либо sortable формат:

DateTime.Now.ToString("s").Substring(0,10).Replace('-',Path.PathSeparator);

либо свой ForceCulture (поддерживающий IDisposable):

using (new ForceCulture())
{
// блок с CultureInfo.InvariantCulture
}
Denis Gladkikh ( ) #
avatar
Сергей Антипов, первый вариант не очень хорош, так как может дать больше 10 символов DateTime.Now.ToString("s"), разделитель может быть и более одного символа, на скриноте это "2010. 08. 30", по этому опасно.

Второй вариант интересен, спасибо.
Дмитрий Басовский ( ) #
avatar
А что мешает изменить

DateTime.Today.ToString("yyyy/MM/dd")

на

DateTime.Today.ToString("yyyy\\/MM\\/dd")

Тогда и проблема отпадет.
Denis Gladkikh ( ) #
avatar
Дмитрий, проще можно сделать и DateTime.Today.ToString(@"yyyy\MM\dd"), и будет работать.
Дмитрий Басовский ( ) #
avatar
Точнее DateTime.Today.ToString(@"yyyy\/MM\/dd")
Denis Gladkikh ( ) #
avatar
Дмитрий, ага, точно.
force ( ) #
avatar
Дмитрий, Денис: в смысле проще? я не понимаю смысла в строке вида 2010\/08\/30 - в лучшем случае, получим то, что система всё проглотит, в худшем - ошибку.
Denis Gladkikh ( ) #
avatar
force, проще в данном случае не говорит о том что лучше. ;)
Дмитрий Басовский ( ) #
avatar
В данном слукае знак "\" показывает, что следующий за ним служебный символ будет восприниматься как обычный. Соответственно и ошибки не должно быть. Z Я только что посмотрел самое начало (первый кусок кода). Там лучше всего будет смотреться string sole = DateTime.Today.ToString("yyyy\\MM\\dd"); И никаких вылетов не будет. Во всяком случе этот синтаксис использую еще с 1-й версии Framework.
Добавить комментарий

Если вы хотите получать уведомления о новых комментариях к данному топику, укажите, пожалуйста, email и отметьте соответствующий пункт в форме. Если вы хотите добавить код в тексте комментария, то заключите его внутри тега [code]...[/code], более того можно уточнить язык, на котором написан данный код при помощи [code cs]...[/code], где вместо cs могут быть cs, html, xml, java, js, php, sql, cpp, css.

 

busy