如何获取当前用户在C#中的时区

我正在build立一个应用程序在mvc3,我想这样做,当用户进入我的网站,我想知道什么是用户时区。 我想知道如何做到这一点在C#不在Java脚本?

这是不可能的服务器端,除非你通过用户的IP地址假设它或让用户设置它的某种forms的configuration文件。 你可以通过javascript获得客户端的时间。

在这里看到的javacript解决scheme: 在JavaScript中获取客户端的时区

如前所述,您需要您的客户端告诉您的ASP.Net服务器有关他们所在的时区的详细信息。

这是一个例子。

我有一个Angular控制器,它从JSON格式的SQL Server数据库加载logging列表。 问题是,这些logging中的DateTime值在UTC时区,我想在本地时区显示用户的date/时间。

我使用JavaScript“ getTimezoneOffset() ”函数确定用户的时区(以分钟为getTimezoneOffset() ,然后将此值附加到我试图调用的JSON服务的URL:

 $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; }); } 

在我的ASP.Net代码中,我提取了timezoneOffset参数…

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

…并将其传递给从数据库加载logging的函数。

这有点乱,因为我想从数据库的每个logging调用C# FromUTCData函数,但是LINQ to SQL不能将原始SQL与C#函数结合起来。

解决scheme是先读入logging,然后遍历它们,将时区偏移量应用于每条logging中的DateTime字段。

 public var LoadDatabaseRecords(int timezoneOffset) { MyDatabaseDataContext dc = new MyDatabaseDataContext(); List<MyDatabaseRecords> 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; } 

它很好地工作,而这个代码是非常有用的时编写一个Web服务,以显示date/时间给世界各地的用户。

现在,我正在苏黎世时间上午11点写这篇文章,但是如果你在洛杉矶读书,你会看到我在凌晨2点(当地时间)对它进行了编辑。 使用这样的代码,您可以让您的网页显示对您的网站的国际用户有意义的date时间。

唷。

希望这可以帮助。

我得到了同样的问题,不幸的是服务器无法知道客户端的时区。 如果你想,你可以发送客户端时区作为标题,同时进行Ajax调用。

在这种情况下,如果你想要更多的信息添加标题这篇文章可能会帮助如何添加标头请求: 我如何添加一个自定义的HTTP标头与JS或JQuery的AJAX请求?

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

如果你不想每次都添加头文件,你可以考虑设置一个cookie,因为cookie和所有的httpRequest一起发送,你可以处理这个cookie来在服务器端获得客户端的时区。 但我不喜欢添加cookie,因为他们与所有http请求一起发送的原因。 谢谢。

我知道用户询问了一个非JavaScript的解决scheme,但我想发布一个JavaScript解决scheme,我想出了。 我发现了一些js库(jsTimezoneDetect,momentjs),但是他们的输出是一个IANA代码,这似乎并没有帮助我在C#中获取TimeZoneInfo对象。 我借鉴了jsTimezoneDetect的想法。 在javascript中,我得到了BaseUtcOffset和DST的第一天并发送到服务器。 服务器然后将其转换为TimeZoneInfo对象。

现在我不在乎客户时区select为“太平洋时间(美国)”还是“下加利福尼亚州”,因为两者都会创build正确的时间转换(我认为)。 如果我find多个匹配,我现在只select第一个find的TimeZoneInfo匹配。

然后,我可以将我的UTC时间从数据库转换为本地时间:

 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<TimeZoneInfo> zoneInfoArray = new List<TimeZoneInfo>(); // 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]; }