如何将字符串(变换偏移)转换为rails中的日期/时间

时间:2018-06-16 20:52:55

标签: ruby-on-rails ruby time

2.5.0 :071 > "2018-06-16 22:39:09 +0200".to_datetime
 => Sat, 16 Jun 2018 22:39:09 +0200 
2.5.0 :072 > "2018-06-16 22:39:09 +0200".to_datetime.utc_offset
 => 7200 
2.5.0 :073 > "2018-06-16 22:39:09 +0200".to_datetime.utc
 => 2018-06-16 20:39:09 UTC 

如何立即将2018-06-16 20:39:09 UTC转换为2018-06-16 22:39:09 +0200

尝试第二个解决方案时

rails console

Running via Spring preloader in process 9869
Loading development environment (Rails 5.2.0)
2.5.0 :001 > orig = "2018-06-16 22:39:09 +0200".to_datetime
 => Sat, 16 Jun 2018 22:39:09 +0200 
2.5.0 :002 > orig_offset = orig.zone # => "+2:00"
 => "+02:00" 
2.5.0 :003 > 
2.5.0 :004 > new = orig.utc
 => 2018-06-16 20:39:09 UTC 
2.5.0 :005 > 
2.5.0 :006 > same_as_orig = new.change(offset: orig_offset)
 => 2018-06-16 20:39:09 +0200 
2.5.0 :007 > same_as_orig == orig # => true
 => false 
2.5.0 :008 > 

1 个答案:

答案 0 :(得分:2)

不知道Rails,我会给出一个纯Ruby的答案(可能本身就有兴趣)。出于这个原因,我无法帮助提取时区名称。我知道可以使用Rails或安装tzinfo gem。

我们从给定的字符串开始:

str = "2018-06-16 22:39:09 +0200"

在Ruby中,我们需要使用类TimeDateTime中的各种方法,因此我们必须require 'time'require 'date'(Rails没有要求,我被告知)。注意DateTime.superclass #=> Date

require 'time'

第一步是从此字符串创建DateTime对象。两种方法是使用DateTime::parseDateTime::strptime,后者是要求更高,因此更可靠的方法。

dtp = DateTime.parse(str)
  #=> #<DateTime: 2018-06-16T22:39:09+02:00 ((2458286j,74349s,0n),+7200s,2299161j)>
dt = DateTime.strptime(str, '%Y-%m-%d %H:%M:%S %z')
  #=> #<DateTime: 2018-06-16T22:39:09+02:00 ((2458286j,74349s,0n),+7200s,2299161j)>

另一种方法是将字符串转换为数组,然后使用DateTime::newTime::new

*all_but_last, offset = str.split(/[- :]/)
  #=> ["2018", "06", "16", "22", "39", "09", "+0200"]
all_but_last
  #=> ["2018", "06", "16", "22", "39", "09"]
offset
  #=> "+02:00"
arr = [*all_but_last.map(&:to_i), offset.insert(-3, ':')]
  #=> [2018, 6, 16, 22, 39, 9, "+02:00"]
DateTime.new(*arr)
  #=> #<DateTime: 2018-06-16T22:39:09+02:00 ((2458286j,74349s,0n),+7200s,2299161j)>
Time.new(*arr)
  #=> 2018-06-16 22:39:09 +0200

暂时相信我,UTC时间实际上是Time的实例。

浏览类Time的方法,我们发现它提供了在UTC时间和本地时间之间转换所需的所有方法,即Time.gmtimeTime#utc_offset(aka,{{ 1}})和Time#getlocal

因此,下一步是使用DateTime#to_timegmt_offset对象DateTime转换为时间对象:

dt

我们现在可以将此t = dt.to_time #=> 2018-06-16 22:39:09 +0200 实例转换为UTC时间:

Time

我之前断言UTC时间为ut = t.gmtime #=> 2018-06-16 20:39:09 UTC 个实例现在可以确认:

Time

要将其转换回本地时间,我们必须保存当地时间的UTC偏移量:

ut.class
  #=> Time

此偏移量以GMT为单位,以秒为单位(7200/3600 = 2小时)。

我们现在可以从offset = t.utc_offset #=> 7200 ut计算当地时间:

offset