Подтвердить что ты не робот

Как отображать DateTime с сокращенным часовым поясом?

Я знаю класс System.TimeZone, а также многие виды использования метод DateTime.ToString(). То, что я не смог найти, - это способ преобразования DateTime в строку, которая в дополнение к информации о времени и дате содержит трехбуквенную аббревиатуру Time Zone (фактически так же, как и всплывающие подсказки StackOverflow для относительных дисплей времени работает.)

Чтобы сделать пример простым для всех, чтобы следовать, а также потреблять, пусть продолжит пример StackOverflow. Если вы посмотрите на всплывающую подсказку, отображаемую в относительные моменты времени, она отобразится с полной датой, временем, включая секунды в двенадцатичасовом формате, обозначением AM/PM, а затем аббревиатурой трехбуквенного времени (в их случае, скоординированной Универсальное время). Я понимаю, что могу легко получить GMT или UTC, используя встроенные методы, но я действительно хочу, чтобы время было локально — в этом случае на веб-сервере.

Если наш веб-сервер работает под управлением Windows Server 2k3 и имеет часовой пояс, установленный в CST (или до тех пор, пока летнее время не вернется, CDT это?), я хотел бы, чтобы наше веб-приложение ASP.NET отображало DateTimes относительно этого часового пояса, а также отформатировано для отображения "CST" в конце. Я понимаю, что я мог бы легко жестко закодировать это, но в интересах надежности я бы предпочел решение, основанное на сервере, на котором установлены настройки среды ОС кода.

Сейчас у меня есть все, кроме аббревиатуры часового пояса, используя следующий код:

myDateTime.ToString("MM/dd/yyyy hh:mm:ss tt")

Что отображается:

10/07/2008 03:40:31 PM

Все, что я хочу (и это не много, обещаю!) для этого сказать:

10/07/2008 03:40:31 PM CDT

Я могу использовать System.TimeZone.CurrentTimeZone и использовать его для правильного отображения "Центральное дневное время", но... это слишком долго для краткости. Я тогда застрял в написании строковой процедуры манипуляции, чтобы вырезать белое пространство и любые буквы, отличные от прописных? Хотя это может сработать, это кажется невероятным взломом для меня...

Googling и оглядываясь здесь не принесло ничего, что применимо к моему конкретному вопросу.

4b9b3361

Ответ 1

Вот мой быстрый метод взлома, который я только что сделал, чтобы обойти это.

public static String TimeZoneName(DateTime dt)
{
    String sName = TimeZone.CurrentTimeZone.IsDaylightSavingTime(dt) 
        ? TimeZone.CurrentTimeZone.DaylightName 
        : TimeZone.CurrentTimeZone.StandardName;

    String sNewName = "";
    String[] sSplit = sName.Split(new char[]{' '});
    foreach (String s in sSplit)
        if (s.Length >= 1)
            sNewName += s.Substring(0, 1);

    return sNewName;
}

Ответ 2

Имеется свободно доступная библиотека TZ4NET, которая имеет эти сокращения. До .NET 3.5 это была одна из альтернатив для преобразования между часовыми поясами.

Если вам не нужна отдельная библиотека, вы можете создать карту разумных аббревиатур с использованием классов TimeZoneInfo, а затем просто предоставить их своему пользователю.

Ответ 4

Если вы потянете аббревиатуру от имени DaylightName/StandardName, вам будет лучше строить строку с помощью StringBuilder, поскольку строки неизменяемы.

    public static string ToCurrentTimeZoneString(this DateTime date)
    {
        string name = TimeZone.CurrentTimeZone.IsDaylightSavingTime(date) ?
            TimeZone.CurrentTimeZone.DaylightName :
            TimeZone.CurrentTimeZone.StandardName;
        return name;
    }

    public static string ToCurrentTimeZoneShortString(this DateTime date)
    {
        StringBuilder result = new StringBuilder();

        foreach (string value in date.ToCurrentTimeZoneString().Split(' '))
        {
            if (value.IsNotNullOrEmptyWithTrim())
            {
                result.Append(char.ToUpper(value[0]));
            }
        }

        return result.ToString();
    }

Конечно, массив, содержащий KeyValuePair, вероятно, лучше всего подходит для многонациональной компании. Если вы хотите побрить несколько минут от сжатого срока, и вы находитесь в американской компании, это работает.

Ответ 5

Используйте nodatime.

Следующая функция принимает DateTime в UTC и форматирует ее с сокращенным временным часом локальной системы. Используйте x в строке формата для сокращенного часового пояса. Найдите пользовательское форматирование здесь.

    public static string ConvertToFormattedLocalTimeWithTimezone(DateTime dateTimeUtc)
    {
        var tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); // Get the system time zone
        var zdt = new ZonedDateTime(Instant.FromDateTimeUtc(dateTimeUtc), tz);
        return zdt.ToString("MM'/'dd'/'yyyy' 'hh':'mm':'ss' 'tt' 'x", CultureInfo.InvariantCulture);
    }

Ответ 6

Это зависит от уровня надежности, который вам нужен.

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

string[] words = tzname.Split(" ".ToCharArray());
string tzabbr = "";
foreach (string word in words)
   tzabbr += word[0];

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

Ответ 7

Хорошо, прошло 4 года (и почти неделю), это время, когда мы привели LINQ в дискуссию...

Объединяя идеи Криага и Боба...

public static String TimeZoneName2(DateTime dt)
{
    var return ToCurrentTimeZoneShortString(dt)
                 .Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
    return sSplit.Aggregate("", (st,w)=> st +=w[0]);
}

Если вы не можете доверять TimeZone, чтобы никогда не возвращать строку с двумя последовательными пробелами:

public static String TimeZoneName3(DateTime dt)
{
    return ToCurrentTimeZoneShortString(dt).Split(' ')
                 .Aggregate("", (st,w)=> st +=w[0]);
}

Ответ 8

Если вы используете < =.Net 3.0, загрузите TZ4Net и используйте OlsonTimeZone.CurrentTimeZone.StandardAbbreviation для > .NET 3.0 используйте NodaTime или другое. Имена часовых поясов не соответствуют ни одному соглашению, где вы можете положиться на простые манипуляции с строкой, чтобы построить аббревиатуру от аббревиатуры. Неправильно 5% времени все еще не так.