Stratégie de fuseau horaire

Je construis une application MVC 3 où les utilisateurs ne sont peut-être pas dans le même fuseau horaire, donc j'ai l'intention de stocker tout en UTC et de passer de l'UTC à l'heure locale dans les vues et le temps local en UTC sur les présentations.

Faire des recherches, mais il ne semble pas y avoir beaucoup de bonnes solutions à cela. Pour être honnête, je m'attendais à ce qu'un attribut soit disponible pour convertir automatiquement le temps UTC en temps local au moins, mais il semble qu'il n'existe pas.

J'ai l'impression d'essayer tout simplement de convertir manuellement toutes les entrées en UTC et de convertir manuellement toutes les vues sur l'affichage de l'heure locale. Les erreurs sont très difficiles à détecter et les erreurs peuvent être détectées lorsque le temps n'est pas converti.

Des suggestions sur la façon de traiter cette stratégie en tant que stratégie générale?

EDIT Tout le monde semble très coincé sur la pièce «Comment puis-je obtenir la fuseau horaire du client», ce qui, comme je l'ai mentionné dans l'un des commentaires, n'est pas mon souci. Je vais bien avec un paramètre d'utilisateur qui détermine leur fuseau horaire, alors supposons que je sais déjà quel est le fuseau horaire du client … qui ne répond pas à mon problème.

À l'heure actuelle, à chaque vue lorsque je rends une date, je devrais appeler une méthode pour la rendre dans le fuseau horaire local depuis l'utc. Chaque fois que j'envoie une date de soumission au serveur, je dois le convertir du fuseau horaire local à UTC. Si j'oublie de le faire, il y aura des problèmes … soit une date soumise sera fausse, soit des rapports côté client et des filtres seront faux.

Ce que j'espérais existait était une méthode plus automatisée, d'autant plus que le modèle de vision est fortement typé dans MVC 3, j'espérais que la somme magique puisse au moins être automatiquement rendue dans un fuseau horaire, sinon gérer la soumission, tout comme la Le format de date ou la gamme peut être contrôlé par un attribut.

Donc comme

[DateRange] Public DateTime MyDate 

Je pourrais avoir quelque chose comme

 [ConvertToUTC(offset)] Public DateTime MyDate 

Quoi qu'il en soit, je pense que ma seule approche serait d'écrire une annotation de données personnalisée pour la rendre dans un fuseau horaire, et une substitution sur le classeur du modèle MVC 3, de sorte que les dates entrantes soient converties à moins que je souhaite envelopper la date dans une méthode appel. Donc, à moins que quelqu'un n'ait de commentaires ou de suggestions supplémentaires, ce sera l'une de ces deux options, je suis tout simplement surpris de ne pas exister déjà pour ce faire.

Si je met en œuvre une solution, je serai certain de la publier.

Edit 2 Quelque chose comme ceci http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx pour les vues MVC 3 et les modèles de vue est ce que je recherche.

Final Edit J'ai marqué epignosisx répondre comme correct, mais aussi quelques commentaires à ajouter. J'ai trouvé quelque chose de semblable ici: http://dalldorf.com/blog/2011/06/mvc3-timezones-1/ Avec une implémentation d'obtenir le fuseau horaire du client en le plaçant dans le cookie pour les personnes qui le souhaitent dans la partie 2 (Lien ci-dessous puisque le lien sur la première partie de l'article à la partie 2 ne fonctionne pas) http://dalldorf.com/blog/2011/09/mvc3-timezones-2/

Il est important de noter avec ces approches que vous DEVEZ éditer et afficher pour au lieu de choses comme TextForFor comme seulement EditFor et DisplayFor utiliser les fournisseurs de métadonnées utilisés pour dire à MVC comment afficher la propriété de ce type sur le modèle. Si vous accédez directement aux valeurs du modèle dans la vue (@ Model.MyDate), aucune conversion n'aura lieu.

Vous pouvez résoudre le problème de la conversion de l'heure UTC par l'utilisateur en utilisant DisplayTemplate à l'échelle du site pour DateTime.

À partir de vos vues, vous utiliserez @ Html.DisplayFor (n => n.MyDateTimeProperty)

Le deuxième problème est plus difficile à aborder. Pour convertir de l'heure locale de l'utilisateur à UTC, vous pouvez remplacer DefaultModelBinder . Plus précisément, la méthode SetProperty . Voici une implantation naïve qui démontre le point. Cela s'applique uniquement à DateTime mais pourrait facilement être étendu à DateTime? . Ensuite, configurez-le comme classeur par défaut dans Global.asax

 public class MyDefaultModelBinder : DefaultModelBinder { protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value) { //special case for DateTime if(propertyDescriptor.PropertyType == typeof(DateTime)) { if (propertyDescriptor.IsReadOnly) { return; } try { if(value != null) { DateTime dt = (DateTime)value; propertyDescriptor.SetValue(bindingContext.Model, dt.ToUniversalTime()); } } catch (Exception ex) { string modelStateKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name); bindingContext.ModelState.AddModelError(modelStateKey, ex); } } else { //handles all other types base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value); } } } 

Tout d'abord, ceci est principalement un double de Comment puis-je déterminer le fuseau horaire d'un utilisateur Web? , Je suis d'accord avec le vote à la majorité pour cette réponse:

La manière la plus populaire (== standard?) De déterminer le fuseau horaire que j'ai vus est simplement demander à l'utilisateur elle-même. Si votre site Web nécessite un abonnement, cela pourrait être enregistré dans les données de profil des utilisateurs. Pour les utilisateurs anonymes, les dates peuvent être affichées sous la forme UTC ou GMT ou certaines d'entre elles.

Cela dit, l'approche la plus courante pour définir automatiquement cette valeur est d'utiliser Date getTimezoneOffset () de javascript. Cela peut ensuite être transmis au serveur via un cookie ou une requête ajax et stocké avec le profil, la session ou le cookie de l'utilisateur.

En fin de compte, je pense toujours que vous devriez permettre aux utilisateurs de modifier ce paramètre afin que vous puissiez déterminer non seulement le décalage UTC, mais aussi l'heure exacte et les informations sur l'heure d'été.

Lors de la collecte des entrées de la conversion des utilisateurs vers et depuis UTC via DateTime devrait suffire. DateTimeOffset est génial lorsque le client est un code géré; Cependant, avec pure html / javascript, il ne va vraiment pas vous acheter beaucoup. En outre, la plupart des applications ne nécessitent pas nécessairement l'information supplémentaire de DateTimeOffset, sauf si vous avez l'intention d'afficher à d'autres utilisateurs les informations de l'heure de l'heure.

J'ai l'impression d'essayer tout simplement de convertir manuellement toutes les entrées en UTC et de convertir manuellement toutes les vues sur l'affichage de l'heure locale. Les erreurs sont très difficiles à détecter et les erreurs peuvent être détectées lorsque le temps n'est pas converti.

Vous ne devez pas dépendre de la diligence requise pour la mise en forme et l'analyse correcte de la date + du temps. Le framework .NET devrait gérer cela pour vous, pour commencer, voir " Comment: définir la culture et la culture UI pour la mondialisation de la page Web ASP.NET ".

Remarque de clôture

Franchement, c'est une douleur dans le cou. Nous avons éliminé la mise en œuvre il ya quelques années et avons commencé à transférer toutes les informations de date + heure en UTC, puis nous utilisons Javascript pour convertir en format horaire et affichage local. C'est vraiment le seul modèle de travail IMHO.

Vous pouvez utiliser quelque chose comme MomentJS pour afficher les dates / heures. Aide avec le formatage et les horaires locaux.

Ceci n'est pas possible automatiquement, vous devrez effectuer un travail manuel.

1 Si vous ne souhaitez pas stocker le fuseau horaire de l'utilisateur dans db

1.1 Sans la page principale: Comme csharptest.net a suggéré d'utiliser le script de script java getDateTimeOffset () pour obtenir le décalage du fuseau horaire, définir la valeur dans les cookies, écrire un module pour vérifier si des cookies sont présents. Insérez le code de script java et le module de cookie à l'aide de cookies.

1.2 Utilisation de la page principale: la même chose, mais pas besoin d'écrire le module pour la vérification.

2 Enregistrez le fuseau horaire de l'utilisateur dans db (le meilleur et le plus simple) Pas besoin d'utiliser javascript pour obtenir le fuseau horaire, il suffit de convertir l'heure de la date en fonction du fuseau horaire de l'utilisateur.