我正在处理一个应用程序,该应用程序检测浏览器的时区并要求用户将时区设置为浏览器检测到的值。
所以,我已经填充了一个选择下拉列表,其中列出了ActiveSupport :: TimeZone :: MAPPING中存在的所有所有键。
现在,我的用户的时区为(GMT-08:00)Pacific / Pitcairn。 ActiveSupport :: TimeZone中不存在许多此类值。
我应该如何处理这些价值观。我检查了许多声称发送Rails支持值的js文件,但它们似乎都没有工作。
如果我在Windows机器中将时区设置为UTC-08:00,那么我的javascript插件会检测时区并发送美国/洛杉矶的值。
我们有一个复选框,不允许Windows机器上的DST计时。 所以在这种情况下,UTC-08:00作为时区,DST框未经检查,我们得到的值太平洋/皮特凯恩。
因此,在美国/洛杉矶和太平洋/皮特凯恩的两个不同价值之前/之前进行匹配是不可能的。
通过UTC偏移设置值,忽略名称也无济于事。我们与太平洋时间(美国和加拿大)的(UTC-08:00)和蒂华纳的(UTC-08:00)有两个独立的价值。那么我该如何决定要设置哪个值。
showTimeZoneInfo: function(member_time_zone, timeZoneInfo, invertTZHash){
var tzValue = jQuery().get_timezone({'defaultvalue' : 'Etc/UTC'});
var railsOffset = TimeZoneFlash.extractOffset(timeZoneInfo[member_time_zone]);
var browserOffset = TimeZoneUtils.zoneWithoutDST();
if ( railsOffset != browserOffset) {
jQuery(".time_zone_text").text(browserOffset + " " + invertTZHash[tzValue]);
jQuery('.cjs_display_time_zone').removeClass('hide');
}
}
现在我们有一个案例,其中invertTZHash不包含Pacific / Pitcairn。它返回一个未定义的值。
我正在为与浏览器时区相比处于不同时区的用户构建警报框。即使是Intl.DateTimeFormat()。resolved.timeZone也无济于事,因为我的大部分流量来自IE和FF浏览器
答案 0 :(得分:3)
时区!=偏移。请参阅timezone tag wiki。因此,只需将其交换为恰好位于UTC-8上的另一个时区并不是一个好主意。您将获取该区域的所有DST规则,这些规则不一定适用。
如果您处理过去的日期,即使Pacific/Pitcairn
也不是纯粹的UTC-8。它从1998年的UTC-08:30变为UTC-08:00 - 你可以看到here。
这是我对ActiveSupport :: TimeZone不满意的原因之一。他们非常清楚in their docs它是有限的:
将TZInfo提供的区域集限制为146个区域的有意义的子集。
这似乎相当武断。是谁决定什么是“有意义的”什么不是?如果它没有意义,那么它就不会在数据库中开始!
你应该看一下使用tzinfo gem,无论如何,它都是ActiveSupport的基础。它具有完整的TZDB及其所有时区数据,而不是有限的子集。
关于时区检测,我不确定您使用什么JavaScript来“检测”时区。您展示了调用某些函数get_timezone
和TimeZoneFlash.extractOffset
,这些函数必须是自定义到您的应用程序或由外部库提供。请详细说明您正在使用的内容。
我所知道的唯一一个用于JavaScript的时区检测库是jsTimeZoneDetect - 这很清楚它只需要一个有根据的猜测。除非你依赖于最新的Chrome和Opera(我认为你不是)的新国际化API,否则没有保证在没有用户参与的情况下检测时区的方法。另请参阅this answer。
我们有一个复选框,不允许Windows机器上的DST计时。所以在这种情况下,UTC-08:00作为时区,DST框未经检查,我们得到的值太平洋/皮特凯恩。
是的,这是一个可怕的现实。恕我直言 - 永远不应该取消选中。如果没有复选框会更好。是否适用DST由时区处理,因此没有充分理由禁用它。我确信他们专门为Pitcairn这样的案件留下了它,因为没有专门针对他们的Windows时区条目。
<强>更新强>
来自您的评论:
我已经有了一个下拉列表。我正在为与浏览器时区相比处于不同时区的用户构建警报框。
使用new Date().getTimezoneOffset()
从JavaScript获取当前偏移量。 (它在几分钟内,符号相反,因此您可能需要一些简单的数学运算。)将其与下拉列表中所选时区的当前偏移量进行比较。 (您应该能够从服务器端代码中获取它。)
如果不匹配,请提醒您的用户。完全不需要jsTimeZoneDetect。
答案 1 :(得分:-1)
一些代码:
timezone = ActiveSupport::TimeZone.all.select { |tz| tz.utc_offset == my_offset }.first
如果您知道UTC偏移量,请在列表中添加new
TimeZone。 See Docs
希望有所帮助!