【问题标题】:Time zones and Localisation时区和本地化
【发布时间】:2011-12-25 21:06:13
【问题描述】:

我目前一直以 UTC 格式存储时间,以便在我开始将多个站点和服务器联机时使事情变得更容易。

在我的模板中将datedatetime 对象转换为字符串以及接受用户输入时出现问题。 UTC 时间下午 6:00 对 PST 中的人来说意义不大。同样,要求用户在 UTC 中输入时间是在要求灾难。

如何以一种聪明且不易出错的方式正确翻译这些值?有没有一种方法可以从 HTTP 请求中确定用户所在的时区?我真的需要一种方法来尽可能少地确定用户的时区。

【问题讨论】:

    标签: python django timezone python-datetime


    【解决方案1】:

    依赖客户自我报告他们的时区的问题在于,您总是有机会(有多大的机会值得商榷)您真正得到的是一个UTC 偏移量。如果您获得 UTC 偏移量,您的逻辑大部分时间都可以正常工作,但实际上仅适用于客户端生成的确切时间戳。任何过去或未来的时间都可能有不同的 UTC 偏移量,如果没有适当的时区数据库,就无法预测。在夏令时边界附近,使用 UTC 偏移会产生灾难性的错误结果。

    除此之外,一些不识字的用户(即奶奶)可能不知道如何设置本地系统的时区;或者隧道会话或虚拟机上的用户可能具有未根据他们的实际偏好设置的“本地”时区。

    根据您对该客户端的了解(IP 等)猜测该客户端的政治时区可能是错误的,并且如果用户无法覆盖猜测,则可能会非常烦人。但是对于匿名用户或新用户注册,我认为使用这种方法作为初始猜测没有任何问题,只要你给用户一些方法来改变它,如果它是错误的。

    我的建议是:

    • 将奥尔森时区作为任何用户配置文件的一部分。可以按国家/地区查找时区,这应该使用户选择时区相对轻松。让 0.01% 关心直接 UTC 选择的用户也:-)
    • 如果您使用基于 IP 的猜测来填充用户配置文件中的默认值,那么如果您使用了良好的查找服务,那么大多数情况下您将是正确的。但如果错误,请允许用户更改。
    • 对于匿名用户,在显示或输入当地时间的任何页面上提供某种小部件,以便他们选择奥尔森时区,其方式与用户配置文件大致相同。将他们选择的值存储在 cookie 中。默认为 UTC 或上述猜测值。

    在实现之前需要以本地时间显示时间戳的基于 Web 的应用程序时,我发现并非所有客户端都将过去和未来日期的 UTC 正确转换为本地时间。我必须在服务器端执行所有转换。这可能需要使用本地时间和奥尔森时区并返回 UTC 时间的 Web 服务。

    【讨论】:

    • 也许我在这里问错了问题。也许我应该问:“StackExchange 如何进行日期转换?”我从来不需要在网站的任何地方输入日期,而且日期似乎只是出现在正确的时区,即使对于网站的公共用户也是如此。引擎盖下真的这么复杂吗?你能总结一下我在你的回答中应该做什么吗?
    • 好吧,我有一个用于 stackoverflow.com 的 usr cookie,其中有一个变量 t。不知道如何解码它,但如果我的时区存储在客户端任何可能的地方。我的桌面是 UTC,这个网站向我展示的所有时间也是如此。我不记得我是否明确设置了 TZ。
    • 我刚刚注销并更改了我的桌面时区,然后访问了该站点。我看到了UTC时间。所以它要么在 cookie 中,要么我的浏览器没有更新它的“本地”概念,或者匿名用户总是在这个网站上看到 UTC。
    • 嗯,你是对的。我想这让我觉得很奇怪,像这样的事情如此复杂且无法自动化。
    • 是的,我就是那种特立独行的人。关于偏移量,我担心浏览器可能存在与此处讨论的一些相同的问题(尽管根据您找到的工具判断,这可能不太可能)。 help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/…
    【解决方案2】:

    我已经这样做了。您可能需要为时区对象安装easy_install pytz。

    import pytz
    import time
    import datetime
    d = time.time()
    
    print datetime.datetime.fromtimestamp(d, pytz.timezone('US/Eastern'))
    print datetime.datetime.fromtimestamp(d, pytz.timezone('US/Central'))
    print datetime.datetime.fromtimestamp(d, pytz.timezone('US/Mountain'))
    print datetime.datetime.fromtimestamp(d, pytz.timezone('US/Pacific'))
    

    这里的 d 变量将 UTC 时间存储为 unix 时间戳。

    【讨论】:

    • 这并不能解决知道用户所在时区的问题。
    • 你说得对,我没有仔细阅读过去启动站点和服务器的内容。从 Web 浏览器获取时间信息通常使用 Javascript 完成。这不应该被信任,但是没有标准的 HTTP 响应标头来传达用户当前的时区,这是最好的猜测。
    • 根据我的经验,代表客户执行转换的 Web 服务是最可靠的解决方案,而且不会太让人头疼。服务应该一次接受/返回多个值以减少请求的数量。
    【解决方案3】:

    您无法从请求标头中可靠地获取用户的时区。这就是为什么大多数网站要求用户在个人资料设置中设置他们的时区。但是,您可以使用各种技巧来尝试获取。一个技巧是使用 Google 的 IP-to-location api 找出用户来自哪里,然后尝试从地理位置猜测时区。这也不是 100% 可靠,但会让你更接近真相。

    刚刚意识到这已经在这里至少被问过一次:get user timezone

    【讨论】:

      【解决方案4】:

      我不会进行 ip 地理定位。它可能非常不准确,尤其是免费服务。只需向用户询问邮政编码或状态,并将其存储在 cookie 中。

      【讨论】:

      • 爱尔兰和其他一些国家没有邮政编码。我会在任何一天对邮政详细信息进行地理定位。
      【解决方案5】:

      您可以使用 javascript(知道当地时间)将用户输入的时间更改为 UTC,然后再将数据发送到您的服务器。然后,以某种格式发送 UTC,以便 javascript 可以将其从 UTC 转换为本地时间。

      例如,要发送到服务器的 UTC 日期:

      (new Date("November 11, 2011 23:13:42")).toUTCString()
      

      并将 UTC 转换为本地时间,用于渲染:

      (new Date("October 17, 1986 15:29:13 UTC")).toLocaleString()
      

      【讨论】:

      • 除非您的 JavaScript VM 中有可用的 Olson 数据库,或者您在 Web 服务中实现本地化,否则这是行不通的。
      • @wberry 我添加了示例。您的浏览器知道它所在的时区。我想我没有发现问题。
      • 许多客户端实现存在缺陷,并且无法对过去和未来日期正确应用夏令时/夏令时政策。例如,如果是夏令时结束的前一天,并且用户输入了明天的某个时间,则在某些客户端中,UTC 时间将关闭一个小时。 Windows 上的 Adob​​e Flash 可以做到这一点。而作为前端作者,这不是你的错,而是你的问题。
      • @wberry 除非您打算向人们询问他们的时区,否则我怀疑这是您能做的最好的事情。每当您编写 javascript 代码时,您都假设 JS 引擎会正确解释它。
      猜你喜欢
      • 2017-05-26
      • 2014-10-22
      • 1970-01-01
      • 2012-01-29
      • 2013-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多