Как я могу преобразовать DateTime в строку с локализованными долями секунды? - PullRequest
10 голосов
/ 21 марта 2012

У меня есть объект DateTime, и я хочу вывести часы, минуты, секунды и доли секунды в виде строки, локализованной для текущей культуры.

Есть две проблемы с этим.

Первая проблема - нет стандартного формата DateTime, который будет показывать доли секунды. По сути, я хочу знать, как получить формат long time DateTime, но с долями секунды.

Я, конечно, мог бы получить DateTimeFormatInfo.LongTimePattern и добавить к нему «.fff» и передать его в DateTime.ToString(), но некоторые из специфических для культуры форматов, особенно в США, заканчиваются на AM / PM. Так что не все так просто.

Вторая проблема заключается в том, что DateTime.ToString(), по-видимому, не локализует десятичный разделитель чисел. Если я решил просто заставить каждую культуру использовать жестко заданный пользовательский формат времени, он все равно не будет создавать локализованную строку, поскольку десятичный разделитель чисел не будет зависеть от культуры.

Чтобы еще больше усложнить ситуацию, в некоторых культурах существуют форматы даты и времени, которые используют периоды как часть своего форматирования. Это затрудняет размещение заполнителя, например точки, и замену его десятичным разделителем для конкретной культуры.

Пока я прибег к этому обходному пути:

string format = string.Format("HH:mm:ss{0}fff",
    CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
string time = DateTime.Now.ToString(format);

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

Примечание. Хотя было бы неплохо решить обе проблемы, для моего конкретного приложения меня больше интересует локализация пользовательского формата даты и времени с долями секунд, чем использование стандартного формата даты и времени.

Ответы [ 3 ]

7 голосов
/ 21 марта 2012

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

Вы могли бы рассмотреть возможность взять длинный формат и просто заменить ": ss" на ": ss.fff", возможно, используя специфический для культуры десятичный разделитель:

string longPattern = culture.DateTimeFormat.LongTimePattern;
if (!longPattern.Contains(":ss"))
{
    // ???? Throw an exception? Test this with all system cultures, but be aware
    // that you might see custom ones...
}
// Only do it if the long pattern doesn't already contain .fff... although if
// it does, you might want to replace it using the culture's decimal separator...
if (!longPattern.Contains(".fff"))
{
    longPattern = longPattern.Replace(":ss", 
        ":ss" + culture.NumberFormat.DecimalSeparator + "fff");
}
string timeText = time.ToString(longPattern, culture);

Чтобы еще больше усложнить ситуацию, в некоторых культурах есть форматы даты и времени, которые используют периоды как часть своего форматирования. Это затрудняет размещение заполнителя, например, периода, и замену его десятичным разделителем для конкретной культуры. Кроме этого, он должен в конечном итоге поставить значение в нужном месте. Вы определенно всегда хотите три цифры, даже если значение является точной секундой (или полсекундами и т. Д.)? Используйте .FFF, если нет.

Я подозреваю, что это , почему не используется специфический для культуры десятичный разделитель. Я сам нашел это странным - действительно, я заставил время Ноды вести себя так же, хотя я не уверен, что это правильно .

В конечном счете, многие подобные проблемы принципиально проблематичны: если у культуры нет фиксированного способа представления «времени с долями секунды», и у вас есть для представления доли секунды, тогда лучшее, что вы сможете сделать, - это немного кусаться.

2 голосов
/ 21 марта 2012

Я думаю, что это даст вам что-то близкое к тому, что вам требуется

var now = DateTime.Now;
var seconds = now.TimeOfDay.TotalSeconds % 60;
var timeText = string.Format(CultureInfo.GetCultureInfo("fr-FR"), 
                             "{0:d} {0:hh:mm:}{1:00.000}", now, seconds);

или просто используйте

var timeText = string.Format(CultureInfo.CurrentCulture, 
                             "{0:d} {0:hh:mm:}{1:00.000}", now, seconds);

Например

  • FR-FR: 20.03.2012 10: 20: 10 088
  • ru: 20.03.2012 10: 21: 08.724
  • ru: 20.03.2012 10: 21: 24.470
0 голосов
/ 21 марта 2012

Обычно я меняю текущую культуру и выполняю нужную мне операцию.

System.Globalization.CultureInfo before = System.Threading.Thread.CurrentThread.CurrentCulture;
try
{
    System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");

    string timestr = DateTime.Now.ToString();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
finally
{
    System.Threading.Thread.CurrentThread.CurrentUICulture = before;
}
...