我有一个Rails应用程序,像所有Rails应用程序一样,使用Ruby的TZInfo库来获取时区信息。此库使用Olson样式的信息,但实现实际上并不解析Olson文件。定义在Ruby中。
我想确保我的服务器和客户端使用相同的时区数据,以便用户不会遇到任何意外。具体来说,我们在Ruby中修补TZInfo数据的速度比新版本的gem快得多。因此,我考虑并拒绝了以下内容:
/usr/share/zoneinfo/*
的内容。 Ruby和zoneinfo
数据会分歧。这给我留下了两个选择:
TZInfo
以实际解析/usr/share/zoneinfo/*
TZInfo
的{{1}}对象序列化为JavaScript,JSON,YAML或其他有用格式的方法仅告诉客户当前时区偏移量是不够的,因为客户端需要为历史(和未来)日期生成时间戳。
答案 0 :(得分:2)
在服务器和客户端上使用实现相同版本的IANA时区数据库的库。当前版本(正如我写的那样)是2013c,可以在原始格式here中找到。
在服务器端,使用TZInfo library表示ruby。它有两个宝石,tzinfo gem和tzinfo-data gem。
如果查看tzinfo-data文档,您会看到有Version
属性与IANA版本匹配。所以tzinfo-data 2013.3显示了IANA版本2013c,它也显示在this page上的文档中。
您在评论中提到数据是硬编码的。这不完全正确。它不是硬编码的,而是代码生成的。当您看到the ruby files带有“硬编码”时区数据时,实际上是使用the original IANA source files生成的。有a custom parser执行此操作,因此每次发布新版本的IANA时区数据库时,都可以生成并发布对tzinfo数据的相应更新。
在客户端,您可以使用several different libraries中的任何一个。大多数人都会做同样的事情 - 从相同的IANA来源开始,以及代码生成一个对网络有意义的文件。通常,这是一个JSON文件。
让我们以其中一个库为例 - Walltime-js。
我们可以看到on github他们已经链接到github上的IANA/Olson tzdb sources。我们可以通过从git中查看精确版本来确保我们使用完全相同的2013c源数据。
最终,我们通过关注IANA来完成代码生成walltime-data.js文件,进行一次小的更改以确保我们拥有完全相同的2013c源数据。新版本看起来像这样:
git submodule init && git submodule update
git submodule foreach 'git checkout f599ad15ce'
cake data
现在我们有了一个由TZDB 2013c构建的walltime-data.js文件。这将转到客户端并由walltime.js使用。
我们还有2013c的tzinfo-data gem,它将位于服务器上并由Ruby中的tzinfo使用。
因此,需要在它们之间传输的唯一数据是时区的ID,例如America/Los_Angeles
。每个库都将使用自己的数据副本和自己的实现,但您可以相信它们指的是相同的东西。
唯一可能使它们表现不同的是,如果它们在解析器或运行时解释数据的方式存在错误。应提请作者注意这些错误。但是你可以避免它们的唯一方法是在两个地方运行 exact 相同的代码和数据 - 这意味着在服务器上使用Node.js而不是Ruby。