Как отобразить DateTime с сокращенным часовым поясом? - PullRequest
37 голосов
/ 08 октября 2008

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

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

Если наш веб-сервер работает под управлением 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 и использовать его, чтобы правильно отображать «Центральное летнее время», но ... для краткости это слишком много. Неужели я застрял в написании процедуры манипуляции со строками, чтобы убрать пробелы и любые не прописные буквы? Хотя это может сработать, это кажется мне невероятным хаком ...

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

Ответы [ 8 ]

19 голосов
/ 27 апреля 2009

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

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;
}
6 голосов
/ 08 октября 2008

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

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

3 голосов
/ 12 декабря 2014

Использование nodatime .

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

    public static string ConvertToFormattedLocalTimeWithTimezone(DateTime dateTimeUtc)
    {
        var tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); // Get the system's time zone
        var zdt = new ZonedDateTime(Instant.FromDateTimeUtc(dateTimeUtc), tz);
        return zdt.ToString("MM'/'dd'/'yyyy' 'hh':'mm':'ss' 'tt' 'x", CultureInfo.InvariantCulture);
    }
2 голосов
/ 29 сентября 2011

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

2 голосов
/ 08 октября 2008

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

См. сокращения часовых поясов .

1 голос
/ 08 октября 2008

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

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

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

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

0 голосов
/ 27 октября 2014

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

0 голосов
/ 12 октября 2012

Хорошо, прошло 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]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...