Come ottenere il fuso orario dell’utente corrente in c #

Sto creando un’applicazione in MVC3 e quando un utente entra nel mio sito desidero conoscere il fuso orario dell’utente. Voglio sapere come farlo in c # non in javaScript?

Questo non è ansible lato server a meno che non lo si presuma tramite l’indirizzo IP dell’utente o si ottenga l’utente per impostarlo in qualche forma di profilo. Si potrebbe ottenere l’ora dei clienti tramite javascript.

Vedi qui per la soluzione javacript: Ottenere il fuso orario del client in JavaScript

Come è stato detto, è necessario che il cliente comunichi al server ASP.Net i dettagli sul fuso orario in cui si trovano.

Ecco un esempio.

Ho un controller angular, che carica un elenco di record dal mio database SQL Server in formato JSON. Il problema è che i valori DateTime in questi record sono nel fuso orario UTC e voglio mostrare all’utente la data / ora nel fuso orario locale.

Determina il fuso orario dell’utente (in minuti) utilizzando la funzione JavaScript ” getTimezoneOffset() “, quindi aggiungo questo valore all’URL del servizio JSON che sto tentando di chiamare:

 $scope.loadSomeDatabaseRecords = function () { var d = new Date() var timezoneOffset = d.getTimezoneOffset(); return $http({ url: '/JSON/LoadSomeJSONRecords.aspx?timezoneOffset=' + timezoneOffset, method: 'GET', async: true, cache: false, headers: { 'Accept': 'application/json', 'Pragma': 'no-cache' } }).success(function (data) { $scope.listScheduleLog = data.Results; }); } 

Nel mio codice ASP.Net, estrae il parametro timezoneOffset

 int timezoneOffset = 0; string timezoneStr = Request["timezoneOffset"]; if (!string.IsNullOrEmpty(timezoneStr)) int.TryParse(timezoneStr, out timezoneOffset); LoadDatabaseRecords(timezoneOffset); 

… e passalo alla mia funzione che carica i record dal database.

È un po ‘complicato, perché voglio chiamare la mia funzione C # FromUTCData su ogni record dal database, ma LINQ su SQL non può combinare SQL raw con funzioni C #.

La soluzione è quella di leggere prima i record, quindi iterare attraverso di essi, applicando l’offset del fuso orario ai campi DateTime di ogni record.

 public var LoadDatabaseRecords(int timezoneOffset) { MyDatabaseDataContext dc = new MyDatabaseDataContext(); List ListOfRecords = dc.MyDatabaseRecords.ToList(); var results = (from OneRecord in ListOfRecords select new { ID = OneRecord.Log_ID, Message = OneRecord.Log_Message, StartTime = FromUTCData(OneRecord.Log_Start_Time, timezoneOffset), EndTime = FromUTCData(OneRecord.Log_End_Time, timezoneOffset) }).ToList(); return results; } public static DateTime? FromUTCData(DateTime? dt, int timezoneOffset) { // Convert a DateTime (which might be null) from UTC timezone // into the user's timezone. if (dt == null) return null; DateTime newDate = dt.Value - new TimeSpan(timezoneOffset / 60, timezoneOffset % 60, 0); return newDate; } 

Funziona bene però, e questo codice è davvero utile quando si scrive un servizio web per visualizzare data / orari per gli utenti in diverse parti del mondo.

In questo momento sto scrivendo questo articolo alle 11:00, ora di Zurigo, ma se lo leggessi a Los Angeles, vedresti che l’ho modificato alle 2 del mattino (ora locale). Usando un codice come questo, puoi ottenere le tue pagine web per mostrare le date che hanno senso per gli utenti internazionali del tuo sito web.

Uff.

Spero che questo ti aiuti.

Ho avuto lo stesso problema, purtroppo non c’è modo per il server di conoscere il fuso orario del client. Se lo desideri, puoi inviare il fuso orario del cliente come intestazione mentre effettui una chiamata ajax.

Nel caso in cui si desideri maggiori informazioni sull’aggiunta dell’intestazione, questo post può aiutare come aggiungere l’intestazione alla richiesta: come posso aggiungere un’intestazione HTTP personalizzata a una richiesta jax con js o jQuery?

 new Date().getTimezoneOffset();//gets the timezone offset 

Se non si desidera aggiungere l’intestazione ogni volta, è ansible pensare di impostare un cookie poiché il cookie viene inviato con tutta la richiesta HTTPRequest in cui è ansible elaborare il cookie per ottenere il fuso orario del client sul lato server. Ma preferisco non aggiungere i cookie, per lo stesso motivo per cui sono stati inviati con tutte le richieste http. Grazie.

So che l’utente ha chiesto una soluzione non javascript, ma volevo pubblicare una soluzione javascript che mi è venuta in mente. Ho trovato alcune librerie js (jsTimezoneDetect, momentjs), ma il loro output era un codice IANA, che non sembrava aiutarmi a ottenere un object TimeZoneInfo in C #. Ho preso in prestito idee da jsTimezoneDetect. In javascript, ricevo BaseUtcOffset e il primo giorno di DST e invio al server. Il server quindi lo converte in un object TimeZoneInfo.

Al momento non mi interessa se il fuso orario del cliente viene scelto come “Pacific Time (US)” o “Baja California”, ad esempio, poiché entrambi creeranno le conversioni orarie corrette (credo). Se trovo più corrispondenze, al momento seleziono solo la prima corrispondenza TimeZoneInfo trovata.

Posso quindi convertire le mie date UTC dal database all’ora locale:

 DateTime clientDate = TimeZoneInfo.ConvertTimeFromUtc(utcDate, timeZoneInfo); 

Javascript

 // Time zone. Sets two form values: // tzBaseUtcOffset: minutes from UTC (non-DST) // tzDstDayOffset: number of days from 1/1/2016 until first day of DST ; 0 = no DST var form = document.forms[0]; var janOffset = -new Date(2016, 0, 1).getTimezoneOffset(); // Jan var julOffset = -new Date(2016, 6, 1).getTimezoneOffset(); // Jul var baseUtcOffset = Math.min(janOffset, julOffset); // non DST offset (winter offset) form.elements["tzBaseUtcOffset"].value = baseUtcOffset; // Find first day of DST (from 1/1/2016) var dstDayOffset = 0; if (janOffset != julOffset) { var startDay = janOffset > baseUtcOffset ? 180 : 0; // if southern hemisphere, start 180 days into year for (var day = startDay; day < 365; day++) if (-new Date(2016, 0, day + 1, 12).getTimezoneOffset() > baseUtcOffset) { dstDayOffset = day; break; } // noon } form.elements["tzDstDayOffset"].value = dstDayOffset; 

C #

  private TimeZoneInfo GetTimeZoneInfo(int baseUtcOffset, int dstDayOffset) { // Converts client/browser data to TimeZoneInfo // baseUtcOffset: minutes from UTC (non-DST) // dstDayOffset: number of days from 1/1/2016 until first day of DST ; 0 = no DST // Returns first zone info that matches input, or server zone if none found List zoneInfoArray = new List(); // hold multiple matches TimeSpan timeSpan = new TimeSpan(baseUtcOffset / 60, baseUtcOffset % 60, 0); bool supportsDst = dstDayOffset != 0; foreach (TimeZoneInfo zoneInfo in TimeZoneInfo.GetSystemTimeZones()) { if (zoneInfo.BaseUtcOffset.Equals(timeSpan) && zoneInfo.SupportsDaylightSavingTime == supportsDst) { if (!supportsDst) zoneInfoArray.Add(zoneInfo); else { // Has DST. Find first day of DST and test for match with sent value. Day = day offset into year int foundDay = 0; DateTime janDate = new DateTime(2016, 1, 1, 12, 0, 0); // noon int startDay = zoneInfo.IsDaylightSavingTime(janDate) ? 180 : 0; // if southern hemsphere, start 180 days into year for (int day = startDay; day < 365; day++) if (zoneInfo.IsDaylightSavingTime(janDate.AddDays(day))) { foundDay = day; break; } if (foundDay == dstDayOffset) zoneInfoArray.Add(zoneInfo); } } } if (zoneInfoArray.Count == 0) return TimeZoneInfo.Local; else return zoneInfoArray[0]; } 

Per DotNet versione 3.5 e successive è ansible utilizzare:

 TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow); 

ma per DotNet Under versione 3.5 puoi gestirlo manualmente in questo modo:

prima ottenere Offset dal client e memorizzarlo nel cookie

 function setTimezoneCookie(){ var timezone_cookie = "timezoneoffset"; // if the timezone cookie not exists create one. if (!$.cookie(timezone_cookie)) { // check if the browser supports cookie var test_cookie = 'test cookie'; $.cookie(test_cookie, true); // browser supports cookie if ($.cookie(test_cookie)) { // delete the test cookie $.cookie(test_cookie, null); // create a new cookie $.cookie(timezone_cookie, new Date().getTimezoneOffset()); // re-load the page location.reload(); } } // if the current timezone and the one stored in cookie are different // then store the new timezone in the cookie and refresh the page. else { var storedOffset = parseInt($.cookie(timezone_cookie)); var currentOffset = new Date().getTimezoneOffset(); // user may have changed the timezone if (storedOffset !== currentOffset) { $.cookie(timezone_cookie, new Date().getTimezoneOffset()); location.reload(); } } 

}

dopodiché puoi usare i cookie nel codice back-end in questo modo:

  public static string ToClientTime(this DateTime dt) { // read the value from session var timeOffSet = HttpContext.Current.Session["timezoneoffset"]; if (timeOffSet != null) { var offset = int.Parse(timeOffSet.ToString()); dt = dt.AddMinutes(-1 * offset); return dt.ToString(); } // if there is no offset in session return the datetime in server timezone return dt.ToLocalTime().ToString(); } 

Puoi provare ad usare sotto lo snipet …

 var timeZone = $"{TimeZoneInfo.Local.StandardName} : {TimeZoneInfo.Local.DisplayName}"; 

Grazie

 System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_TIMEZONE"] ;