2008-10-07 10 views
35

Jestem świadomy klasy System.TimeZone, a także wielu zastosowań metody DateTime.ToString(). To, czego nie udało mi się znaleźć, jest sposobem na konwersję DateTime na ciąg znaków, który oprócz informacji o czasie i dacie zawiera trzyliterowy skrót strefy czasowej (w rzeczywistości w bardzo podobny sposób, jak podpowiedzi StackOverflow dla względnego wyświetlacz czasu działa).Jak wyświetlić DateTime ze skróconą strefą czasową?

Aby ułatwić przykład użytkownikom naśladowania i konsumpcji, kontynuujmy przykład StackOverflow. Jeśli spojrzysz na etykietkę narzędziową wyświetlaną w czasie względnym, wyświetli się ona z pełną datą, czasem obejmującym sekundy w formacie dwunastogodzinnym, oznaczeniem AM/PM, a następnie trzyliterowym skrótem strefy czasowej (w ich przypadku, skoordynowanym Czas uniwersalny). Zdaję sobie sprawę, że mogę łatwo uzyskać GMT lub UTC za pomocą wbudowanych metod, ale to, czego naprawdę chcę, to czas, ponieważ jest lokalnie — w tym przypadku na serwerze sieciowym.

Jeśli nasz serwer sieciowy ma system Windows Server 2k3 i ma ustawioną strefę czasową na CST (lub, aż do daylight saving przełącza się z powrotem, CDT to jest?), Chciałbym, aby nasza aplikacja internetowa ASP.NET wyświetlała wartości DateTimes w stosunku do w tej strefie czasowej, a także sformatowany do wyświetlania "CST" na końcu. Rozumiem, że mogłem z łatwością zakodować to, ale w interesie solidności wolałbym rozwiązanie oparte na serwerze z ustawieniami środowiska operacyjnego kodu kodu.

Teraz mam wszystko poza skrótem strefy czasowej przy użyciu następującego kodu:

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

który wyświetla:

10/07/2008 03:40:31 PM

Wszystko Chcę (i nie jest to zbyt wiele, obietnica!), Żeby to powiedzieć:

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

Mogę używać System.TimeZone.CurrentTimeZone i używać go do prawidłowego wyświetlania "Central Daylight Time", ale ... to trochę za długo dla zwięzłości. Czy utknąłem wtedy na pisaniu procedury manipulowania strunami w celu usunięcia białych znaków i dowolnych małych liter? Chociaż to może zadziałać, to wydaje mi się nie do zniesienia ...

Googling i rozejrzenie się tutaj nie przyniosło niczego, co dotyczyłoby mojego konkretnego pytania.

Odpowiedz

1

To zależy od poziomu odporności, jakiego potrzebujesz.

Prawdopodobnie będziesz potrzebował jakiegoś hakera w obie strony. Łatwym sposobem byłoby podzielenie ciągu na spacje, a następnie połączenie pierwszej litery każdego słowa. tj.

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

To nie zadziała dla każdej strefy czasowej na świecie, ale będzie działać dla większości z nich. Jeśli potrzebujesz go solidniej, prawdopodobnie będziesz musiał utworzyć mapę, która odwzoruje nazwy stref czasowych na ich skróty.

2

Utworzę tabelę odnośników, która konwertuje nazwę strefy czasowej na jej skrót. Jeśli mecz nie zostanie znaleziony, możesz zwrócić pełną nazwę strefy.

Zobacz time zone abbreviations.

6

Dostępna jest bezpłatna biblioteka, TZ4NET, zawierająca te skróty. Przed .NET 3.5 była to jedna z alternatyw dla konwersji między strefami czasowymi.

Jeśli nie chcesz osobnej biblioteki, możesz wygenerować mapę rozsądnych skrótów przy użyciu klas TimeZoneInfo, a następnie po prostu dostarczyć je do swojego użytkownika.

19

Oto moja metoda szybkiego włamania, którą właśnie opracowałem, aby obejść ten problem.

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

To podejście ma kilka wad. Na przykład w Arizonie, gdzie korzystają z Mountain Standard Time i nie obserwują czasu letniego, .NET ma DaylightName i StandardName z "US Mountain Standard Time", które pokaże "UMST" z twoją metodą. Spodziewałbym się zamiast tego "MST" (zarówno latem, jak i zimą). Niestety, platforma .NET wydaje się tu nie nadawać, więc uciekłem się do statycznej tablicy odnośników. – codemonkey

+0

Nie będzie działać w przypadku wielu stref czasowych, np. ** ACT ** _Acre Time_ (UTC -5) – Tanmay

2

Jeśli ciągnąc skrót od DaylightName/StandardName, masz zamiar być lepiej buduje ciąg przy użyciu StringBuilder, na ciągi są niezmienne.

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

Oczywiście tablica zawierająca KeyValuePair jest prawdopodobnie najlepsza dla wielonarodowej firmy. Jeśli chcesz zgolić kilka minut z napiętego terminu i jesteś w amerykańskiej firmie, to działa.

+1

Myślę, że połączenie dwóch znaków z trzech znaków nie jest wcale takie złe i nie usprawiedliwia użycia tutaj StringBuildera, szczególnie dlatego, że i tak idziesz w lewo i prawo. – Martijn

0

Ok, to było 4 lata (i prawie tydzień), to czas przywieźliśmy LINQ do dyskusji ...

Zestawiając Criag i pomysły Bob ...

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

chyba że można zaufać strefy czasowej, aby nie zwracać ciąg z dwóch kolejnych miejsc:

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

Jeśli używasz < = .NET Framework 3.0, a następnie pobrać i używać OlsonTimeZone.CurrentTimeZone TZ4Net .StandardBrak dla> .Net 3.0 używa NodaTime lub innego. Nazwy stref czasowych nie są zgodne z żadną konwencją, w której można polegać na prostej manipulacji łańcuchami znaków w celu skonstruowania skrótu z akronimu. Złe 5% czasu jest nadal błędne.

+0

Czy zamierzasz odejść od osiągnięcia zysku w 95% przypadków? – micahhoover

2

Użyj nodatime.

Następująca funkcja pobiera DateTime w czasie UTC i formatuje ją ze skróconą strefą czasową lokalnego systemu. Użyj x w ciągu znaków w skróconej strefie czasowej. Poszukaj niestandardowego formatowania here.

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); 
    } 
Powiązane problemy