【问题标题】:Can You Determine Timezone from Request Variables?你能从请求变量中确定时区吗?
【发布时间】:2010-09-25 04:57:46
【问题描述】:

有没有办法在服务器端进行时区偏移,通过 http 读取请求中的内容,而不是将所有内容发送到客户端并让它处理?

【问题讨论】:

    标签: asp.net datetime .net-3.5 timezone globalization


    【解决方案1】:

    我是如何使用 javascript 和 MVC 解决它的:

    首先,在主站脚本上,我添加了以下代码:

    var clientOffset = getCookie("_clientOffset");
    var currentOffset = new Date().getTimezoneOffset() * -1;
    var reloadForCookieRefresh = false;
    
    if (clientOffset  == undefined || clientOffset == null || clientOffset != currentOffset) {
        setCookie("_clientOffset", currentOffset, 30);
        reloadForCookieRefresh = true;
    }
    
    if (reloadForCookieRefresh)
        window.location.reload();
    
    function setCookie(name, value, days) {
        var expires = "";
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            expires = "; expires=" + date.toUTCString();
        }
        document.cookie = name + "=" + (value || "") + expires + "; path=/";
    }
    
    function getCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
        }
        return null;
    }
    

    在服务器端的动作过滤器内:

    public class SetCurrentRequestDataFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            // currentRequestService is registered by request using IoC container
            var currentRequestService = iocResolver.Resolve<ICurrentRequestService>();
    
            if (context.HttpContext.Request.Cookies.AllKeys.Contains("_clientOffset"))
            {
                currentRequestService.ClientOffset = int.Parse(context.HttpContext.Request.Cookies.Get("_clientOffset").Value);
            }
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      有没有办法在服务器端进行时区偏移,通过 通过 http 读取请求中的内容,而不是发送 一切交给客户并让其处理?

      当我遇到与 WCF Web 服务相同的问题时,这是我想出的解决方案:

      How to get a WCF Web Service to return DateTimes in user's local timezone

      基本上,我获取我的 JavaScript/Angular 代码来确定用户的时区,然后将此值传递给我的 WCF Web 服务之一。

      注意我有一个名为getListOfRecords 的网络服务,它采用一个参数,即时区偏移值。

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

      从那里,我的 C# 代码读取数据库记录,将该时区偏移应用于 UTC DateTime 值,并将其返回给客户端。

      【讨论】:

      • 我遇到了另一个问题,这使情况更加复杂。这如何在我的夏令时时区处理明年 12 月的返回日期。如果它只使用偏移量,那么许多时区匹配,并且其中大多数不使用夏令时。
      【解决方案3】:

      我们可以在服务器端使用以下代码获取时区,而不是从客户端发送值。

      private TimeZoneInfo GetRequestTimeZone()
          {
              TimeZoneInfo timeZoneInfo = null;
              DateTimeOffset localDateOffset;
              try
              {
                  localDateOffset = new DateTimeOffset(Request.RequestContext.HttpContext.Timestamp, Request.RequestContext.HttpContext.Timestamp - Request.RequestContext.HttpContext.Timestamp.ToUniversalTime());
                  timeZoneInfo = (from x in TimeZoneInfo.GetSystemTimeZones()
                                  where x.BaseUtcOffset == localDateOffset.Offset
                                  select x).FirstOrDefault();
              }
              catch (Exception)
              {
              }
              return timeZoneInfo;
          }
      

      谢谢...

      【讨论】:

      • 您是否在设置为 UTC 的服务器和设置为您的实际时区的客户端上尝试过此操作。
      • 你对我很感兴趣,以至于浪费了我几分钟的时间来测试这个,但是很抱歉。去钓鱼。有趣的概念。如果浏览器默认只发送本地时间和请求头。
      • 这似乎只是一种确定服务器时区的迂回方式,可以更简单地完成。
      【解决方案4】:

      这更复杂,但我之前不得不求助于这种情况,因为机器和用户配置文件设置有时与访问者的偏好不匹配。例如,英国访问者从澳大利亚服务器临时访问您的网站。

      1. 按照@balabaster 的建议使用地理定位服务(例如 MaxMind.com),以获取与其 IP 匹配的区域(最好使用 Global.Session_Start)。这对本地 ISP 来说是一个很好的匹配,但对 AOL 来说不是那么好。将此偏移量存储在会话 cookie 中。

      2. 或者在用户进入网站时使用 JavaScript 获取时区偏移量作为表单提交/重定向的一部分。这是浏览器的当前偏移量,但不一定是访问者的首选区域。将此值用作默认值;存储在另一个会话 cookie 中。

        
        <script type="text/javascript" language="JavaScript">
        var offset = new Date();
        document.write('<input type="hidden" id="clientTzOffset" name="clientTzOffset" value="' + offset.getTimezoneOffset() + '"/>');
        </script>
        
      3. 允许访问者通过持久性 cookie(对于匿名用户)和其帐户配置文件中的字段(如果经过身份验证)更新区域。

      持久值 #3 from 覆盖会话值。您还可以为经过身份验证的用户存储相同的持久 cookie,以便在他们登录之前显示时间。

      【讨论】:

        【解决方案5】:

        在页面卸载之前的任何事件中...Request.ServerVariables。如果您想要他们的物理时区,那么您检查他们的 IP 地址并使用 IP 到地理位置的转换工具。

        我不确定是否有其他方法可以做到这一点,所以如果你需要他们的计算机配置的时区,它必须等待页面加载以获取 javascript...

        【讨论】:

        • 感谢您创建了我今天听到的最长版本的不。
        • 我以前一直在想,为什么每次用手机用 Opera Mini 上网时,我都会看到挪威奥斯陆的本地化广告,后来才意识到这是由 IP 到地理位置的转换造成的……它只是碰巧奥斯陆离我住的地方有几个时区:-)
        • ChanChan:你总是可以依靠我;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多