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

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

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

первая проблема - нет стандарта DateTime формат, который покажет дробные секунды. Я по существу хочу знать, как получить долго формат 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 ответов


первая проблема заключается в том, что нет стандартного формата 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 если не.

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

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


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

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
  • en-GB: 20/03/2012 10:21: 08.724
  • en-US: 20.03.2012 10: 21: 24.470

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

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