2010-04-28 4 views
2

J'ai un DateTime stocké en heure UTC que je souhaite afficher à l'utilisateur à l'heure locale depuis un contrôle GridView. Comment puis-je convertir mon DateTime à l'heure de l'utilisateur (pas l'heure locale de mon serveur)? Voici mon champ actuel tel qu'il apparaît dans la collection Colonnes GridView:Affichage DateTime dans GridView en utilisant l'heure de l'utilisateur

<asp:BoundField DataField="RunTime" HeaderText="Run Time" 
    SortExpression="RunTime" DataFormatString="{0:f}" /> 

Répondre

3

Vous devez savoir le fuseau horaire de l'utilisateur - par exemple, à partir des données de profil d'utilisateur ou de votre site Web conserve. Alternativement, vous pouvez essayer de guestimate basé sur des données GeoIP, bien que cela puisse être suspect parce que l'utilisateur peut ne pas utiliser ce fuseau horaire particulier sur leur ordinateur.

.NET ne sait pas automatiquement à quelle heure l'utilisateur utilise l'extrémité distante.

2

votre meilleur pari serait de stocker la préférence de l'utilisateur du fuseau horaire. Vous ne pouvez pas deviner correctement le fuseau horaire à partir des informations du navigateur.

Voici un tutoriel rapide pour stocker le fuseau horaire sélectionné dans Session, et créer un contrôle rapide qui peut être sur chaque page pour mettre à jour les dates imprimées.

http://www.dotnet-friends.com/articles/asp/artinasp381efae4-87c8-41ae-9427-2ae75edd9594.aspx

3

Vous pouvez utiliser JavaScript pour trouver le fuseau horaire de l'utilisateur:

var userTime =(new Date().getTimezoneOffset()/60)*(-1);

Ensuite, le stocker dans un champ caché ou le transmettre en tant que paramètre. Dans votre page, vous devrez remplacer l'événement RowDataBound de GridView, trouver l'heure et le convertir en utilisant les méthodes de conversion de DateTime.

éditer: Probablement la manière la plus sûre de faire ceci est d'avoir l'utilisateur stocker leur fuseau horaire dans un profil. De cette façon, la désactivation de JavaScript n'affectera pas votre application.

modifier: Code côté serveur

static void Main() 
    {    
     const string timeFmt = "{0,-30}{1:yyyy-MM-dd HH:mm}"; 
     DateTime dt = DateTime.Now.ToUniversalTime(); 
     for (int i = -12; i <= 12; i++) 
     { 
      DateTime converted = ConvertToLocalDateTime(dt, i); 
      Console.WriteLine(timeFmt, "Offset: " + i , converted); 
     } 
     Console.ReadLine(); 
    } 

    static DateTime ConvertToLocalDateTime(DateTime dateTime, int offset) 
    { 
     TimeZoneInfo destinationTimeZone = TimeZoneInfo.GetSystemTimeZones() 
      .Where(x => x.BaseUtcOffset.Hours.Equals(offset)).FirstOrDefault(); 

     var rule = destinationTimeZone.GetAdjustmentRules().Where(x => 
      x.DateStart <= dateTime && dateTime <= x.DateEnd) 
      .FirstOrDefault(); 

     TimeSpan baseOffset = TimeSpan.Zero; 
     if(rule != null) 
     { 
      baseOffset -= destinationTimeZone.IsDaylightSavingTime(dateTime) ? 
       rule.DaylightDelta : TimeSpan.Zero; 
     } 

     DateTimeOffset dto = DateTimeOffset.Parse(dateTime.ToString()); 
     return new DateTime(TimeZoneInfo.ConvertTimeFromUtc(dateTime, destinationTimeZone).Ticks + baseOffset.Ticks); 
    } 

Voir: http://msdn.microsoft.com/en-us/library/system.timezone(VS.90).aspx

+0

Je veux faire quelque chose de similaire, mais au lieu d'utiliser la date actuelle pour obtenir le décalage (et calculer incorrectement certaines dates), j'ai besoin d'utiliser RunTime pour obtenir le décalage. Comment puis-je faire cela à partir d'un GridView? –

+1

Vous avez dit que RunTime était une date UTC. Vous devez d'abord obtenir l'offset de la date actuelle de l'utilisateur (via JavaScript), puis ajuster RunTime avec ce nouveau décalage. .NET n'a aucun moyen de connaître les informations sur le fuseau horaire du client car tout fonctionne côté serveur. Exemple: RunTime est 15:00 UTC. JS obtient un décalage de -6 pour le client. RunTime doit soustraire 6 heures afin d'afficher l'heure dans le fuseau horaire du client (9h00). – kamranicus

+0

Et comment compensez-vous lorsque la date est en janvier dernier? Mon décalage actuel serait de -5 pour l'heure d'été, ce qui me ferait perdre une heure de janvier. –

3

Pour mon site, je viens d'utiliser jQuery pour faire une requête AJAX à un fuseau horaire gestionnaire HTTP qui enregistrerait le fuseau horaire dans session, puis j'ai créé une méthode d'extension "ToVisitorTime" qui utiliserait cette valeur.

Dans votre modèle de base ou en-tête de la page:

<script type="text/javascript" src="/lib/js/jquery.js"></script> 

<asp:Placeholder id="plcTimezoneScript" Visible="false" runat="server"> 
    <script type="text/javascript"> 
     function getVisitorTimezone() 
     { 
      // get visitor timezone offset 
      var curDt = new Date(); 
      $.post("/ajax/TimezoneOffset.ashx", { 
       offset: -(curDt.getTimezoneOffset()/60) 
      }); 
     } 

     $(getVisitorTimezone); 
    </script> 
</asp:Placeholder> 

ensuite de le cacher si vous avez déjà empoigné la session, dans le behind:

protected void Page_Load(object sender, EventArgs e) 
{ 
    object sessOffset = Session["OFFSET"]; 

    if (sessOffset == null) 
    { 
     plcTimezoneScript.Visible = true; 
    } 
} 

Pour le gestionnaire /ajax/TimezoneOffset.ashx :

using System; 
using System.Web; 
using System.Web.SessionState; 

public class TimezoneOffset : IHttpHandler, IRequiresSessionState 
{ 

    public void ProcessRequest (HttpContext context) { 
     context.Response.ContentType = "text/plain"; 
     object sessOffset = context.Session["OFFSET"]; 

     if (context.Request.RequestType == "POST") 
     { 
      if (sessOffset == null) 
      { 
       string offset = context.Request.Form.Get("offset"); 
       int Offset = 0; 

       if (!String.IsNullOrEmpty(offset) 
        && Int32.TryParse(offset, out Offset)) 
       { 
        context.Session.Add("OFFSET", Offset); 
       } 
      } 
     } 
    } 

    public bool IsReusable { 
     get { 
      return false; 
     } 
    } 

} 

Puis une méthode d'extension pour prendre soin d'afficher le bon moment (renvoie un DateTime objet pour un traitement ultérieur si nécessaire). N'oubliez pas de le stocker dans une classe statique:

public static DateTime ToVisitorTime(this DateTime UtcDate) 
{ 
    // use timezone offset, if set 
    object TimezoneOffset = HttpContext.Current.Session["OFFSET"]; 

    if (TimezoneOffset != null) 
    { 
     int Offset = 0; 

     if (Int32.TryParse(TimezoneOffset.ToString(), out Offset)) 
     { 
      UtcDate = UtcDate.AddHours(Offset); 
     } 
     else 
     { 
      UtcDate = UtcDate.ToLocalTime(); 
     } 
    } 
    else 
    { 
     // well, at least show the local server time 
     UtcDate = UtcDate.ToLocalTime(); 
    } 

    return UtcDate; 
} 

Cela a été pris d'un tutoriel, je l'ai pas encore publié mais devrait faire ce que vous avez besoin. Un inconvénient est que sur le premier chargement de la page, rien ne sera dans le bon moment.

Vous devriez probablement utiliser une méthode JS, étant donné que cela nécessite déjà que JS fonctionne. Je recommanderais le plugin Datejs et utiliserais jQuery pour remplacer automatiquement les dates utc.

+0

Pour obtenir une traduction correcte, j'ai besoin d'obtenir chaque décalage séparément en utilisant RunTime au lieu de la date actuelle. Votre script ne traduira correctement les dates qu'au cours de ma partie actuelle de l'heure d'été. –

+0

En fait, le script fonctionnera bien. Vous devez changer le BoundField dans un TemplateField et ajuster la valeur de RunTime: <% # Convert.ToDateTime (Eval ("RunTime")). ToVisitorTime(). ToString ("f")%> Le JS uniquement récupère le décalage de fuseau horaire de l'utilisateur, il ne modifie aucune date. ToVisitorTime suppose que vous transmettez une date UTC. – kamranicus

+0

Ce script échouera si je l'exécute aujourd'hui (29 avril) à une date de janvier, qui n'observait pas l'heure d'été. Il utilisera le décalage pour aujourd'hui, soit une heure de plus que le décalage dont j'aurais besoin pour janvier. Peut-être que je pourrais lancer un script depuis le TemplateField, mais je ne sais pas si c'est possible. –

Questions connexes