Jak pracować ze strefami czasowymi w ASP.NET?

Pracuję nad projektem "system przypomnień online" (ASP.NET 2.0 (C#) / SQL Server 2005)

Ponieważ jest to usługa przypominająca, która wyśle wiadomość do użytkowników w określonym terminie. Ale problem polega na tym, że użytkownicy nie są z określonego kraju, są z całego świata i z różnych stref czasowych. Teraz podczas rejestracji pytam o strefę czasową użytkowników w taki sam sposób, jak windows pyta naszą strefę czasową w czasie instalacji.

Ale nie rozumiem, czy user selected (+5.30) or something timezone then how to handle this time zone in my asp.net podanie. Jak pracować według strefy czasowej.

I proszę zasugerować, czy jest jakiś lepszy sposób na obsługę stref czasowych w tej aplikacji ??

Thanks

Author: marc_s, 2009-05-07

7 answers

Pierwszą rzeczą jest upewnienie się, w której strefie czasowej znajdują się Twoje dane. Polecam upewnić się, że każda przechowywana DateTime jest przechowywana w czasie UTC (użyj DateTime.ToUniversalTime(), aby ją zdobyć).

Aby zapisać przypomnienie dla użytkownika, musisz podać bieżący czas UTC, dodać lub usunąć różnicę stref czasowych użytkownika i przekonwertować nowy czas z powrotem na UTC; to jest to, co chcesz zapisać w DB.

Następnie, gdy chcesz sprawdzić przypomnienia do wysłania, po prostu musisz zajrzeć do baza danych przypomnień do wysłania teraz, zgodnie z czasem UTC; zasadniczo Pobierz wszystkie przypomnienia, które mają znacznik czasu, który jest przed DateTime.Now.ToUniversalTime().

Update with some implementation specific: Możesz uzyskać listę stref czasowych za pomocą metody TimeZoneInfo.GetSystemTimeZones(); możesz ich użyć, aby wyświetlić listę stref czasowych dla użytkownika. Jeśli przechowujesz właściwość Id z wybranej strefy czasowej, możesz utworzyć z niej instancję klasy TimeZoneInfo i obliczyć czas UTC dla danej lokalnej daty/czasu wartość:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("<the time zone id>");
// May 7, 08:04:00
DateTime userDateTime = new DateTime(2009, 5, 7, 8, 4, 0);
DateTime utcDateTime = userDateTime.Subtract(tzi.BaseUtcOffset);
 27
Author: Fredrik Mörk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-07 06:06:34

Polecam zawsze używać czasu UTC (GMT) po stronie serwera (w kodzie, bazie danych itp.) i konwertować czas z UTC na czas lokalny tylko do celów wyświetlania. Oznacza to, że wszystkie manipulacje czasowe - w tym oszczędzanie czasu w bazie danych, wykonywanie obliczeń itp. - powinny być wykonywane przy użyciu UTC.

Problem polega na tym, jak Twój kod-behind wie, jaka jest strefa czasowa przeglądarki klienta? Powiedzmy, że użytkownik wprowadza jakąś wartość daty/czasu (np. 12/30/2009 14: 30) w formularzu i przesyła go na serwer. Zakładając, że użytkownik przesłał czas lokalny, w jaki sposób serwer wie, jak przekonwertować tę wartość NA UTC?

Aplikacja może poprosić Użytkownika o określenie strefy czasowej (i zapisanie jej w trwałym pliku cookie lub bazie danych), ale wymaga dodatkowego wysiłku ze strony Użytkownika, a Twoja aplikacja musiałaby zaimplementować logikę i ekrany w tym celu. Byłoby lepiej, gdyby aplikacja mogła automatycznie określić strefę czasową klienta .

I rozwiązano ten problem za pomocą funkcji getTimezoneOffset JavaScript, która jest jedynym API, które może informować serwer o różnicy czasu między czasem lokalnym na kliencie i GMT. Ponieważ jest to API po stronie klienta, wykonałem następujące czynności: po stronie serwera sprawdź niestandardowy plik cookie sesji przechowujący wartość przesunięcia czasu, a jeśli nie jest dostępny, przeładuj stronę (tylko podczas wywołań GET, a nie POST) z dodaną logiką JavaScript, aby wygenerować przesunięcie czasu i zapisz to w ciastku. Od strony klienta jest to prawie przezroczyste(raz w trakcie sesji przeładowuję stronę NA GET). Gdy mam offset w pliku cookie, stosuję go do funkcji zarządzania czasem w zależności od kierunku konwersji czasu (UTC na czas lokalny lub czas lokalny NA UTC).

Może to zabrzmieć nieco skomplikowanie i jest, ale po napisaniu funkcji pomocniczych, integracja tej funkcji w witrynie była kwestią wykonania pojedynczego wywołania w Page_Load (stron, które potrzebowały konwersja czasu), oraz korzystanie z procedur konwersji czasu podczas wysyłania i pobierania wartości czasu do iz przeglądarki. Oto przykład, jak można go użyć:

using My.Utilities.Web;
...

// Derive the form class from BaseForm instead of Page.
public class WebForm1: BaseForm
{
...
private void Page_Load(object sender, System.EventArgs e)
{
  // If we only want to load the page to generate the time
  // zone offset cookie, we do not need to do anything else.
  if (InitializeLocalTime())
    return;

  // Assume that txtStartDate is a TextBox control.
  if (!IsPostback)
  {
     // To display a date-time value, convert it from GMT (UTC)
     // to local time.
     DateTime startDate = GetStartDateFromDB(...);
     txtStartDate.Text  = FormatLocalDate(startDate);
     ...
  }
  else
  {
     // To save a date-time value, convert it from local
     // time to GMT (UTC).
     DateTime tempDate  = DateTime.Parse(txtStartDate.Text);
     DateTime startDate = ConvertLocalTimeToUtc(tempDate);
     SaveStartDateInDB(startDate, ...);
     ...
  }
}
...
}
Jeśli potrzebujesz więcej szczegółów, sprawdź It ' s About Time: Localizing Time in ASP.NET Aplikacje artykuł (sorry, ale nie mam bezpośredniego linku do artykułu na stronie wydawcy, ponieważ asp.netPRO ogranicza dostęp tylko do płatnych subskrybentów; są jednak linki do kopii PDF). Chciałbym móc pisać przykład z artykułu, ale nie chcę naruszać praw autorskich; jednak oto projekt budowy biblioteki pomocniczej, która ma wszystkie niezbędne funkcje i dokumentację (po prostu zignoruj rzeczy, których nie potrzebujesz).

Aktualizacja: artykuł został opublikowany online z przykładowym projektem przez nowego wydawcę tutaj .

 18
Author: Alek Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-23 01:13:34

Problem ze wszystkimi odpowiedziami jest taki, że nie biorą pod uwagę tego, co Prashant próbuje osiągnąć. Jeśli użytkownik swojego systemu w dniu poprzedzającym zmianę czasu letniego ma przesunięcie +12 i ustawia przypomnienie na następny dzień, jego przesunięcie, gdy przypomnienie ma zostać uruchomione, wyniesie +13.

Dlatego możesz używać bieżącego offsetu tylko dla czegoś, co dzieje się teraz. Chociaż zgadzam się z wszystkimi, że wszystkie czasy po stronie serwera (z wyjątkiem tych używanych tylko do wyświetlania) powinny być przechowywane w UTC.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 02:26:06

Możesz użyć struktury DateTimeOffset zamiast DateTime, jeśli korzystasz z frameworku 2.0 lub nowszego.

DateTimeOffset reprezentuje punkt w czasie w stosunku do czasu UTC, więc powinno być łatwiejsze do pracy w tym przypadku.

 2
Author: Rune Grimstad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-07 06:36:53

Istnieją 2 kroki:

  • Wykrywanie różnych stref czasowych po stronie klienta za pomocą Javascript:

    var dt = new Date();
    var diffInMinutes = -dt.getTimezoneOffset();
    
  • Następnie po stronie serwera, kod C# do konwersji czasu serwera na czas klienta w oparciu o wykryte przesunięcie strefy czasowej powyżej:

------------------------;

string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
    clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}
 1
Author: Minh Nguyen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-14 14:00:10

Zasadniczo, wszystko, co musisz zrobić, to dodać offset (godziny + minuty) do czasu lokalnego, który został wprowadzony przez użytkownika. Dodanie przesunięcia w zasadzie daje DateTime w strefie czasowej UTC (zasadniczo GMT).

Zazwyczaj najłatwiej jest ustandaryzować wszystkie czasy NA UTC, aby logika aplikacji nie musiała radzić sobie z przesunięciami.

Ta strona ma kilka dobrych przykładów: http://msdn.microsoft.com/en-us/library/bb546099.aspx

 0
Author: Andy White,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-07 05:25:50

Problem polega na tym, że przesunięcie od UTC będzie się różnić w różnych porach roku-każda strefa czasowa ma swoje własne zasady. (Nauczyłem się tego na własnej skórze podczas opracowywania aplikacji do planowania sal konferencyjnych.)

Wygląda na to, że jest tu wbudowana obsługa: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

Sam tego nie próbowałem, ale wydaje się, że obiecuje poprawną konwersję, biorąc pod uwagę czas letni.

Jeśli nie, tutaj jest (drogie) użyłem komercyjnego narzędzia: http://www.worldtimeserver.com/time_zone_guide/

 0
Author: Matt Sherman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-12 05:16:18