【问题标题】:Accounting for daylight savings in rails webapp and iCal在 rails webapp 和 iCal 中考虑夏令时
【发布时间】:2013-09-15 09:23:36
【问题描述】:

对,这对我来说有点混乱,所以我要尝试从顶部解释!

我有一个 Rails 网络应用程序。这是一个内部公司应用程序,仅在英国使用。 该应用程序所做的其中一件事是管理会议。 会议有开始的日期和时间。表单上有一个日期/时间选择器,允许用户选择会议的日期和时间。我将这个日期原样保存到数据库中。所有会议持续 2 小时,因此结束时间只需开始 + 2 小时。

例子:

2013-06-23 6:45PM in the form is stored in the db as 2013-06-23 18:45:00
2013-12-23 6.45pm in the form is stored in the db as 2013-12-23 18:45:00

请注意,第一个日期在夏令时 (BST) 期间,第二个日期在 GMT 期间。我实际上不在乎是格林威治标准时间还是英国夏令时:会议绝对是在那个时间举行的。

在 rails webapp 中,我只需从数据库中打印出确切的日期和时间——当然,格式很好!

现在,有时我会向会议的组织者以及与他们会面的人发送一封电子邮件。这封电子邮件告诉他们会议的日期和时间等,还包括一个 iCal (.ics) 文件供他们放入他们的(通常是 Outlook,但也包括 Apple 或 gmail)日历。

我遇到的问题是(使用上述示例)Outlook 显示的会议如下:

Meeting #1: Start: 23/06/2013 7:45pm, End: 23/06/2013 9:45pm
Meeting #2: Start: 23/12/2013 6:45pm, End: 23/12/2013 8:45pm

请注意,由于 BST/GMT 的问题,它已经调整了第一个。

.ics 文件的文本包含以下代码:

第 1 次会议:

BEGIN:VCALENDAR
...
DTEND:20130623T204500Z
DTSTART:20130623T184500Z
...
END:VCALENDAR

会议 #2:

BEGIN:VCALENDAR
...
DTEND:20131223T204500Z
DTSTART:20131223T184500Z
...
END:VCALENDAR

所以我使用 Z 时区 (UTC) 对日期/时间进行编码。我理解这就是为什么 Outlook 错误地将 UTC 时间转换为 #1 的 BST 时间而单独留下 #2(因为 GMT == UTC)

我的问题是:如何阻止这种情况发生?我希望安排会议的时间是绝对的实际时间,无论 GMT/BST:下午 6:45

我应该将日期时间作为 UTC 存储在数据库中吗?这将如何完成(我假设它适用于所有日期,而不仅仅是会议开始日期)。当我在 webapp 中显示它们时,如何将它们重新转换回 实际 日期时间?

额外: 我的初始化程序/time_formats.rb 中有一个条目,如下所示:

:ical => "%Y%m%dT%H%M00Z" 

所以日期会像“20130623T184500Z”一样出现。我在构建 ics 时使用它。我认为这是问题所在 - 如果日期/时间在 BST 期间,我不想使用 Z,而是使用其他东西?

【问题讨论】:

  • 说到在数据库中将日期存储为UTC,DB字段是MSSQL datetime。该字段中没有任何内容来指示 UTC 偏移量......那么如何知道是否加/减一个小时?
  • rails c d = DateTime.now => Wed, 11 Sep 2013 12:25:10 +0100 d.utc => Wed, 11 Sep 2013 11:25:10 +0000 所以我可以在保存到数据库之前将日期转换为UTC。如何撤消检索时的转换?
  • 请注意(在阅读了 Rails 默认情况下在数据库中使用 UTC 之后):我没有在任何地方配置任何与时区相关的东西 - 这就是日期/时间一直以来的工作方式(保存它们按原样),我认为它是默认的。

标签: ruby-on-rails utc dst icalendar


【解决方案1】:

您的问题是您的日期/时间格式。你有:

DTSTART:20130623T184500Z

在您的 .ics 文件中,这对应于 19:45 BST(因为英国夏令时是 UTC+1)。

您应该做几件事。首先,您可以简单地从日期末尾删除“Z”。这意味着时间会继承日历或底层应用程序的时区。

假设运行 Outlook 的机器都在欧洲/伦敦时区,这将起作用。如果没有,或者如果您想更安全一点,您还应该在 BEGIN: VCALENDAR 行之后指定以下内容:

X-WR-TIMEZONE:Europe/London

这为所有未明确指定的日期指定默认时区。

最后,如果由于任何原因这不起作用,那么您需要明确定义您的日期时间。首先,您需要将欧洲/伦敦的时区定义添加到日历中。您需要的信息可在http://www.tzurl.org/zoneinfo-outlook/Europe/London.ics 获得。然后您需要确保所有日期时间的格式为:

DTSTART;TZID=Europe/London:20130623T184500

最后一种方法是最好的,因为这意味着如果您的需求扩展到其他时区,您将能够相对轻松地处理它们。

【讨论】:

  • 好的,谢谢。我曾尝试添加时区(以及 BST/GMT 的定义),但结果相同。实际上,我终于弄清楚发生了什么——我的 rails 应用程序实际上存储了 UTC 日期(默认情况下),但它也认为它自己的时区是 UTC!所以本质上它是存储 local 日期。更改应用程序以知道它位于欧洲/伦敦,因此数据库中的日期现在都是准确的 UTC,这意味着我可以在 iCals 中使用 Z 日期格式,outlook 和 rails 应用程序都将 UTC 日期转换回用户选择的实际日期 - Presto!
【解决方案2】:

很抱歉我自己回答这个问题,但如果其他人遇到这个问题,我发现这是我的特定问题的原因。请注意,re timezones 上面的答案也很有意义!

我的 rails 应用程序将 UTC 日期时间存储在数据库中(默认情况下) 但是,它也认为它自己的时区是 UTC,这似乎也是默认的。

其结果本质上是存储本地日期,无论如何都是 UTC 本地日期。更改应用程序以知道它位于欧洲/伦敦,因此数据库中的日期现在都是准确的 UTC(意思是,如果我目前在 BST,它们会休息一个小时)

我现在可以在 iCals 中使用 Z 日期时间格式,outlook 和 rails 应用程序都将 UTC 日期转换回查看用户区域设置的实际日期时间(目前每个人都适用于欧洲/伦敦)。这就是我想要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-14
    • 1970-01-01
    • 2013-09-22
    • 2018-01-01
    • 2012-07-03
    • 2017-11-13
    • 2020-09-12
    • 2020-03-01
    相关资源
    最近更新 更多