ruby 带时区的Strptime

vulvrdjw  于 2023-02-15  发布在  Ruby
关注(0)|答案(9)|浏览(157)

我用DateTime.strptime解析了一个字符串,字符串中日期的时区是CET,但是Ruby创建了一个UTC DateTime对象,它当然有一个2hrs的偏移量。
目前我正在解决DateTime.strptime().change(:offset => "+0020")的问题,但我很肯定这不是它的工作方式。
谁能告诉我做这件事的正确方法?

kx7yvsdv

kx7yvsdv1#

可以使用to_time_in_current_zone将日期转换为时区。例如:

Date.strptime('04/07/1988', '%m/%d/%Y').to_time_in_current_zone
gt0wga4j

gt0wga4j2#

我一直在努力解决这个问题,试图解析表单中的日期字符串,并独立于服务器时间保存它。我遵循的过程是这样的。我保证RoR和Ruby时区设置为UTC。如果服务器也是UTC时间,这会更容易。
我使用ActiveSupport:TimeZone格式(如US/Eastern)存储用户的区域设置。我有一个解释日期函数,它可以解释不包含时区或偏移量的日期字符串

# date_str looks something like this `12/31/2014 6:22 PM`
# tz is a string containing an ActiveSupport::TimeZone name like `US/Eastern`
def interpret_date(date_str, tz)
  Time.use_zone tz do
    parsed_dt = DateTime.strptime(date_str, '%m/%d/%Y %H:%M %p')
    offset = parsed_dt.in_time_zone(tz).utc_offset
    parsed_dt.advance(seconds: -(offset)).in_time_zone(tz)
  end
end

当然,这并不是一个完美的解决方案,但它确实有效。确保时区正确的步骤如下:
1.根据我们的格式解析日期字符串
1.根据该时区的时间提取当前utc偏移量(如果您解析的日期恰好是dst,而您的本地时间不是东部时间的dst,则必须执行此操作,这将确保dst是解析时间的本地时间)
1.将时间转换为我们的目标语言环境,并允许时间移动,添加正确的偏移量

6ju8rftf

6ju8rftf3#

对于Rails 5之前的版本,可以使用以下方法:

t0 = Time.strptime("2018-05-01", "%Y-%m-%d") # Or whatever
t1 = Time.zone.now.change(year: t0.year, month: t0.month, day: t0.day, hour: t0.hour, min: t0.min, sec: t0.sec, usec: t0.usec)
p3rjfoxz

p3rjfoxz4#

试试这个

(date + Rational(5,24)).new_offset(-Rational(5,24))

你在这里做什么:假设您要更改为时区5

date + Rational(5,24)

我会在你的约会时间上加5个小时,保持时区不变。
之后,如何调整偏移量以恢复原始数据并获得您想要的时区。

n8ghc7c1

n8ghc7c15#

我无法删除已接受的答案
正如@LeeJarvis在下面的评论部分指出的,Chronic.parse不接受:time_class选项,所以这个答案是有缺陷的,虽然它看起来很有效,但实际上并没有(除非慢性病很快允许传递:time_class选项)。
慢性宝石真的很强大。
我是这样使用它的:

Chronic.parse("next 5:00 pm", 
:time_class => ActiveSupport::TimeZone.new(User.first.time_zone)).utc

在我上面的例子中,User.first.time_zone是"太平洋时间(美国和加拿大)"。
Chronic支持多种格式,请访问https://github.com/mojombo/chronic查看
确保传递:time_class选项并转换为UTC(在文档中,Chronic在调用parse之前设置:time_class。我避免这种方法,因为它可能导致应用程序中的其他部分无法工作)
时区的文档位于http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html

3lxsmp7m

3lxsmp7m6#

我是这样使用它的:

ruby-1.9.2-head :001 > require 'date'
 => true 
ruby-1.9.2-head :002 > fmt = "%m-%d-%Y %H:%M:%S %Z"
 => "%m-%d-%Y %H:%M:%S %Z" 
ruby-1.9.2-head :003 > DateTime.strptime "10-26-2011 10:16:29 CET", fmt
 => #<DateTime: 2011-10-26T10:16:29+01:00 (212186380589/86400,1/24,2299161)> 
ruby-1.9.2-head :004 > DateTime.strptime "10-26-2011 10:16:29 UTC", fmt
 => #<DateTime: 2011-10-26T10:16:29+00:00 (212186384189/86400,0/1,2299161)> 
ruby-1.9.2-head :005 > DateTime.strptime "10-26-2011 10:16:29 PST", fmt
 => #<DateTime: 2011-10-26T10:16:29-08:00 (212186412989/86400,-1/3,2299161)>

你是这个意思吗?

pkwftd7m

pkwftd7m7#

这在Rails 5中有效:

Time.zone.strptime("2017-05-20 18:20:10", "%Y-%m-%d %H:%M:%S")

返回指定时区中的时间。

14ifxucb

14ifxucb8#

至少从Rails 4.2开始(可能更早,尚未测试),只要使用Time#strptime而不是DateTime.strptime,就会自动应用当前时区:

> DateTime.strptime('12/28/2016 5:00 PM', '%m/%d/%Y %H:%M %p')
=> Wed, 28 Dec 2016 17:00:00 +0000

> Time.strptime('12/28/2016 5:00 PM', '%m/%d/%Y %H:%M %p')
=> 2016-12-28 17:00:00 -0800
3qpi33ja

3qpi33ja9#

我正在"strptiming"这个字符串:

19/05/2014 8:13:26 a.m.

本地时间戳,在我的例子中是Auckland NZ,字符串中没有时区戳,如图所示。
据我所知,Time.strptime使用服务器时区作为基础。
在我的情况下,一般的良好实践是,我的服务器运行在UTC时区,所以字符串的每次解析都创建一个时间对象,time to +0000(UTC):

2014-05-19 08:13:26 +0000

然后转换为in_time_zone(Time.zone),得到:

Mon, 19 May 2014 20:13:26 NZST +12:00

可以看到,这比我想要的实际时间晚了12个小时(UTC偏移)。
我试着使用上面的+' Auckland', '...%Z'技巧,没有任何改变。然后我使用上面的+ '+1200', '...%Z'技巧,它工作正常。
然而我担心夏天的时间,然后解析将在一个小时,所以这是我的结果:

Time.strptime(call_data[:datetime].gsub(/\./, "").gsub(/am/, "AM").gsub(/pm/, "PM") + (Time.zone.now.time_zone.utc_offset/3600).to_s.ljust(4,'0').rjust(6,' +'), '%d/%m/%Y %I:%M:%S %p %Z').in_time_zone(Time.zone)

结果:

Mon, 19 May 2014 08:13:26 NZST +12:00

它不是特别优雅,但它的工作。

相关问题