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 >
答案 0 :(得分:2)
不知道Rails,我会给出一个纯Ruby的答案(可能本身就有兴趣)。出于这个原因,我无法帮助提取时区名称。我知道可以使用Rails或安装tzinfo gem。
我们从给定的字符串开始:
str = "2018-06-16 22:39:09 +0200"
在Ruby中,我们需要使用类Time和DateTime中的各种方法,因此我们必须require 'time'
或require 'date'
(Rails没有要求,我被告知)。注意DateTime.superclass #=> Date
。
require 'time'
第一步是从此字符串创建DateTime
对象。两种方法是使用DateTime::parse或DateTime::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::new或Time::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.gmtime,Time#utc_offset(aka,{{ 1}})和Time#getlocal。
因此,下一步是使用DateTime#to_time将gmt_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