web-dev-qa-db-fra.com

Comment travailler avec les fuseaux horaires dans ASP.NET?

Je travaille sur un projet de "système de rappel en ligne" (ASP.NET 2.0 (C #)/SQL Server 2005)

Comme il s'agit d'un service de rappel qui enverra le courrier aux utilisateurs à des dates particulières. Mais le problème est que les utilisateurs ne viennent pas d'un pays spécifique, ils viennent du monde entier et de fuseaux horaires différents. Maintenant, lorsque je m'inscris, je demande le fuseau horaire des utilisateurs de la même manière que Windows demande notre fuseau horaire au moment de l'installation.

Mais je ne reçois pas le si l'utilisateur a sélectionné (+5,30) ou quelque chose de fuseau horaire, alors comment gérer ce fuseau horaire dans mon application asp.net. Comment travailler selon le fuseau horaire.

Et s'il vous plaît suggérer s'il existe une meilleure façon de gérer les fuseaux horaires dans cette application ??

Merci

27
Prashant

La première chose est de vous assurer dans quel fuseau horaire vos données se trouvent. Je recommanderais de vous assurer que tout DateTime que vous stockez est stocké en heure UTC (utilisez la fonction DateTime.ToUniversalTime() pour l'obtenir).

Lorsque vous devez enregistrer un rappel pour un utilisateur, vous aurez besoin de l'heure UTC actuelle, ajoutez ou supprimez la différence de fuseau horaire de l'utilisateur et reconvertissez cette nouvelle heure en UTC; c'est ce que vous souhaitez stocker dans la base de données.

Ensuite, lorsque vous souhaitez vérifier les rappels à envoyer, il vous suffit de rechercher dans la base de données les rappels à envoyer maintenant, en fonction de l'heure UTC; obtenir essentiellement tous les rappels qui ont un horodatage avant DateTime.Now.ToUniversalTime().

pdate avec quelques spécificités d'implémentation: Vous pouvez obtenir une liste des fuseaux horaires à partir de la méthode TimeZoneInfo.GetSystemTimeZones(); vous pouvez les utiliser pour afficher une liste de fuseaux horaires pour l'utilisateur. Si vous stockez la propriété Id à partir du fuseau horaire sélectionné, vous pouvez créer une instance de classe TimeZoneInfo à partir de celle-ci et calculer l'heure UTC pour une valeur de date/heure locale donnée:

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
Fredrik Mörk

Je recommanderais de toujours utiliser l'heure UTC (GMT) côté serveur (en code-behind, base de données, etc.) et convertir l'heure UTC en heure locale à des fins d'affichage uniquement. Cela signifie que toutes les manipulations de temps - y compris gagner du temps dans la base de données, effectuer des calculs, etc. - doivent être effectuées en utilisant UTC.

Le problème est: comment votre code-behind sait-il quel est le fuseau horaire du navigateur client? Supposons que l'utilisateur saisisse une valeur de date/heure (telle que 30/12/2009 14:30) dans le formulaire et la soumet au serveur. En supposant que l'utilisateur a soumis l'heure locale, comment le serveur sait-il comment convertir cette valeur en UTC?

L'application peut demander à l'utilisateur de spécifier le fuseau horaire (et de l'enregistrer dans un cookie ou une base de données persistante), mais cela nécessite un effort supplémentaire de la part de l'utilisateur, et votre application devra implémenter la logique et les écrans pour cela. Ce serait plus agréable si l'application pouvait déterminer automatiquement le fuseau horaire du client .

J'ai résolu ce problème à l'aide de la fonction getTimezoneOffset de JavaScript, qui est la seule API qui peut indiquer au serveur la différence de temps entre l'heure locale sur le client et GMT. Comme il s'agit d'une API côté client, j'ai fait ce qui suit: côté serveur, recherchez un cookie de session personnalisé contenant la valeur de décalage temporel, et s'il n'est pas disponible, rechargez la page (uniquement lors des appels GET et non POST) avec une logique JavaScript ajoutée pour générer le décalage horaire et l'enregistrer dans le cookie. Du côté client, cela est presque transparent (une fois pendant la session, je recharge une page sur GET). Une fois que j'ai le décalage dans le cookie, je l'applique aux fonctions de gestion du temps en fonction du sens de la conversion de l'heure (UTC en heure locale, ou heure locale en UTC).

Cela peut sembler un peu compliqué, et cela l'est, mais après avoir écrit des fonctions d'aide, l'intégration de cette fonctionnalité dans le site consistait à effectuer un appel unique dans▶Load (des pages nécessitant une conversion de temps), et en utilisant des routines de conversion de temps lors de l'envoi et de la récupération de valeurs de temps vers et depuis le navigateur. Voici un exemple de la façon dont il peut être utilisé:

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, ...);
     ...
  }
}
...
}

Si vous avez besoin de plus de détails, consultez l'article It's About Time: Localizing Time in ASP.NET Applications (désolé, mais je n'ai pas de lien direct vers l'article sur le site de l'éditeur, depuis asp. netPRO restreint l'accès aux abonnés payants uniquement; il existe des liens vers PDF copies, cependant). J'aimerais pouvoir publier l'exemple de l'article, mais je ne veux pas violer le copyright; cependant , voici un projet de construction d'une bibliothèque d'aide qui a toutes les fonctionnalités et la documentation nécessaires (ignorez simplement ce que vous n'avez pas avoir besoin).

MISE À JOUR: L'article a été mis en ligne avec un exemple de projet par le nouvel éditeur ici .

17
Alek Davis

Le problème avec toutes les réponses jusqu'à présent est qu'elles ne tiennent pas compte de ce que Prashant essaie de réaliser. Si l'utilisateur de son système la veille des changements d'heure d'été a un décalage de +12 et définit un rappel pour le lendemain, son décalage lorsque le rappel est censé être déclenché sera de +13 à la place.

C'est pourquoi vous ne pouvez utiliser le décalage actuel que pour quelque chose qui se produit actuellement. Bien que je convienne avec tout le monde que toutes les heures côté serveur (sauf éventuellement celles utilisées uniquement pour l'affichage) doivent être stockées en UTC.

3
Paul

Vous voudrez peut-être envisager d'utiliser la structure DateTimeOffset au lieu de DateTime si vous utilisez le framework 2.0 ou une version ultérieure.

Le DateTimeOffset représente un point dans le temps par rapport à l'heure UTC, il devrait donc être plus facile de travailler avec dans ce cas.

2
Rune Grimstad

Il y a 2 étapes:

  • Détectez différents fuseaux horaires côté client en utilisant Javascript:

    var dt = new Date();
    var diffInMinutes = -dt.getTimezoneOffset();
    
  • Ensuite, côté serveur, code C # pour convertir l'heure du serveur en heure du client en fonction du décalage de fuseau horaire détecté ci-dessus:

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

string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
    clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}
1
Minh Nguyen

Le problème est que la compensation par rapport à l'UTC variera à différents moments de l'année - chaque fuseau horaire a ses propres règles. (J'ai appris cela à la dure lors du développement d'une application de planification de salle de réunion.)

On dirait qu'il y a un support intégré ici: http://msdn.Microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

Je ne l'ai pas essayé moi-même, mais il semble promettre la conversion correcte, en tenant compte de l'heure d'été.

Sinon, voici un outil commercial (coûteux) que j'ai utilisé: http://www.worldtimeserver.com/time_zone_guide/

0
Matt Sherman

Fondamentalement, il vous suffit d'ajouter le décalage (heures + minutes) à l'heure locale que l'utilisateur a entrée. L'ajout du décalage vous donne essentiellement un DateTime dans le fuseau horaire UTC (essentiellement GMT).

Il est généralement plus facile de standardiser tous vos temps en UTC, afin que votre logique d'application n'ait pas à gérer les décalages.

Cette page contient quelques bons exemples: http://msdn.Microsoft.com/en-us/library/bb546099.aspx

0
Andy White