Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails 3中,如何解析ISO8601日期字符串以获取TimeWithZone实例?_Ruby On Rails_Date_Timezone_Iso8601 - Fatal编程技术网

Ruby on rails 在Rails 3中,如何解析ISO8601日期字符串以获取TimeWithZone实例?

Ruby on rails 在Rails 3中,如何解析ISO8601日期字符串以获取TimeWithZone实例?,ruby-on-rails,date,timezone,iso8601,Ruby On Rails,Date,Timezone,Iso8601,这是我的解决办法。有更紧凑的吗 > time_from_client = "2001-03-30T19:00:00-05:00" => "2001-03-30T19:00:00-05:00" > time_from_client.to_datetime => Fri, 30 Mar 2001 19:00:00 -0500 > timezone_offset = time_from_client.to_datetime.offset.numerator

这是我的解决办法。有更紧凑的吗

> time_from_client = "2001-03-30T19:00:00-05:00"
 => "2001-03-30T19:00:00-05:00" 

> time_from_client.to_datetime
 => Fri, 30 Mar 2001 19:00:00 -0500 

> timezone_offset = time_from_client.to_datetime.offset.numerator
 => -5 

> tz = ActiveSupport::TimeZone[timezone_offset]
 => (GMT-05:00) America/New_York

> tz.class
=> ActiveSupport::TimeZone 
查看
ActiveSupport::TimeWithZone
。简短回答:使用
Time.parse(Time\u字符串)。在\u时区中

[9] pry(main)> Time.parse("2001-03-30T19:00:00-05:00")
=> 2001-03-30 19:00:00 -0500
[10] pry(main)> Time.parse("2001-03-30T19:00:00-05:00").class
=> Time
[11] pry(main)> Time.parse("2001-03-30T19:00:00-05:00").in_time_zone
=> Sat, 31 Mar 2001 00:00:00 UTC +00:00
[12] pry(main)> Time.parse("2001-03-30T19:00:00-05:00").in_time_zone.class
=> ActiveSupport::TimeWithZone
如果您希望它位于另一个时区:

[13] pry(main)> Time.parse("2001-03-30T19:00:00-05:00").in_time_zone("America/Los_Angeles")
=> Fri, 30 Mar 2001 16:00:00 PST -08:00

不幸的是,这是不可能的,至少在没有变得更聪明的情况下是不可能的

要理解为什么必须区分时区和UTC偏移:

  • 时区是指,并且可以选择具有
  • A
考虑从分区到偏移的映射:您还必须知道相关时间以及分区,以便决定是应用标准偏移还是日光偏移

走另一条路要困难得多。再一次,仅仅有偏移量是不够的,因为我们不知道偏移量是指标准时间还是指夏时制。但这一次我们遇到了一个鸡/蛋的问题:即使我们也有时间,我们也需要知道这个区域,以确定那个时间是标准时间还是白天。但是,我们没有区域


下面是您的一个工作示例,您使用的是2001年3月30日星期五19:00:00,这恰好是标准时间(EST),所以第一次通过时看起来不错:

> time_from_client = "2001-03-30T19:00:00-05:00"
 => "2001-03-30T19:00:00-05:00" 


> time_from_client.to_datetime
 => Fri, 30 Mar 2001 19:00:00 -0500 

> timezone_offset = time_from_client.to_datetime.offset.numerator
 => -5 

> tz = ActiveSupport::TimeZone[timezone_offset]
 => (GMT-05:00) America/New_York
我们有美国/纽约


但是看看如果我们跳到夏季会发生什么,比方说,
2001年6月30日19:00:00
。来自客户端的
时间\u的偏移分量现在将是
-04:00
,这是纽约的夏时制偏移(EDT)

免责声明:下一步实际上不起作用,因为
分子
4/24
四舍五入到
1/6
,您将得到一个不正确的
时区偏移量
。因此,我调整了您的实现并使用了
utc\u offset

> timezone_offset = time_from_client.to_datetime.utc_offset
 => -14400

> tz = ActiveSupport::TimeZone[timezone_offset]
 => (GMT-04:00) Atlantic Time (Canada)
现在可以看到问题了,我们得到的不是
美国/纽约
而是
大西洋时间(加拿大)
。后者是标准偏移量
-04:00
的区域名称之一,因为只能使用标准
utc_偏移量
查找,并且不知道日光

如果你遵循这一点得出结论,你最终会得到以下反直觉的
parse

> tz.parse "2001-06-30T19:00:00-04:00"
 => Sat, 30 Jun 2001 20:00:00 ADT -03:00
我假设这里发生的是
TimeWithZone
看到这是六月,所以调整到大西洋日光偏移量,
-03:00


值得注意的是,如果不考虑日光,并获得传递到
ActiveSupport::TimeZone[]
的标准偏移量,您仍然无法获得正确的分区,因为偏移到分区的映射不是一对一的

如下所示:

ActiveSupport::TimeZone.all.select { |z| z.utc_offset == -14400 }
=> [(GMT-04:00) Atlantic Time (Canada), (GMT-04:00) Georgetown, (GMT-04:00) La Paz, (GMT-04:00) Santiago]
这就是我认为这是不可能的原因,除非您碰巧也有原始ISO 8601字符串的位置信息


顺便说一句,如果您采用这种方法,我建议使用Node.js库,它可以使用分区几何图形进行位置到分区的查找。

不幸的是,这不是答案。我希望TimeWithZone实例所在的时区已包含在我从客户端获取的iso8601字符串中。当客户端作为另一个参数通过时区时,您的解决方案将起作用。请注意,在第一次解析时,您已经丢失了时区信息。谢谢,这是一个很好的答案!它应该是被接受的,伊姆霍。
ActiveSupport::TimeZone.all.select { |z| z.utc_offset == -14400 }
=> [(GMT-04:00) Atlantic Time (Canada), (GMT-04:00) Georgetown, (GMT-04:00) La Paz, (GMT-04:00) Santiago]