Ruby on rails 带时区的strtime

Ruby on rails 带时区的strtime,ruby-on-rails,ruby,timezone,datetimeoffset,strptime,Ruby On Rails,Ruby,Timezone,Datetimeoffset,Strptime,我有一个字符串,我用DateTime.strtime解析它。字符串中日期的时区是CET,但是Ruby创建了一个UTC DateTime对象,当然它的偏移量是2小时 目前我正在使用DateTime.strtime().change(:offset=>“+0020”)解决这个问题,但我很确定这不是它的工作方式 有人能告诉我做这件事的正确方法吗?我使用它的方式如下: ruby-1.9.2-head :001 > require 'date' => true ruby-1.9.2-hea

我有一个字符串,我用
DateTime.strtime
解析它。字符串中日期的时区是CET,但是Ruby创建了一个UTC DateTime对象,当然它的偏移量是2小时

目前我正在使用
DateTime.strtime().change(:offset=>“+0020”)
解决这个问题,但我很确定这不是它的工作方式


有人能告诉我做这件事的正确方法吗?

我使用它的方式如下:

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)> 
ruby-1.9.2-head:001>需要“日期”
=>正确
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.strtime“10-26-2011 10:16:29 CET”,fmt
=> # 
ruby-1.9.2-head:004>DateTime.strtime“10-26-2011 10:16:29 UTC”,fmt
=> # 
ruby-1.9.2-head:005>DateTime.strtime“10-26-2011 10:16:29太平洋标准时间”,fmt
=> # 

这就是你的意思吗?

我不能删除一个被接受的答案

正如@LeeJarvis在下面的评论部分指出的,
Chronic.parse
不接受
:time\u class
选项。因此,这个答案是错误的,虽然它看起来是有效的,但实际上并没有(除非Chronic允许很快传递一个
:time\u类
选项)


慢性宝石真的很强大

我是这样使用它的:

Chronic.parse("next 5:00 pm", 
:time_class => ActiveSupport::TimeZone.new(User.first.time_zone)).utc
在我上面的例子中,
User.first.time\u zone
是“太平洋时间(美国和加拿大)”

Chronic支持多种格式,请访问

确保在调用parse之前传递
:time\u class
选项并转换为UTC(在文档中,慢性设置
:time\u class
。我避免使用这种方法,因为它可能会导致应用程序中的其他部分无法工作)

时区的文档位于

您可以将日期转换为时区,并将
转换为当前时区中的时间。例如:

Date.strptime('04/07/1988', '%m/%d/%Y').to_time_in_current_zone
我正在“strptiming”这个字符串:

19/05/2014 8:13:26 a.m.
本地时间戳,在我的例子中是奥克兰新西兰,字符串中没有时区戳,可以看到

尽我所能告诉你时间。strtime使用服务器时区作为基准

在我的情况下,以及一般的良好实践中,我的服务器在UTC时区运行,因此字符串的每次解析最终都会创建一个时间对象,时间为+0000(UTC):

然后在时区(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

它不是特别优雅,但很有效。

我一直在努力解决同样的问题,试图从表单中解析日期字符串,并独立于服务器时间保存它。我所遵循的过程就是这样。 我保证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
这当然不是一个完美的解决方案,但它确实有效。 确保时区正确的步骤包括:

  • 根据我们的格式解析日期字符串
  • 根据该时区的时间提取当前utc偏移量(如果您正在解析的日期恰好在dst中,而您的本地时间不是东部时间的dst,则我们必须这样做,这将确保dst是解析时间的本地时间)
  • 将时间转换为我们的目标区域设置,并允许时间在添加正确偏移量的情况下移动
  • 至少从Rails 4.2开始(可能更早,尚未测试),只要您使用
    Time#strtime
    而不是
    DateTime.strtime
    ,当前时区将自动应用:

    > 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
    
    这适用于Rails 5:

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

    返回指定时区中的时间。

    对于pre-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)
    

    我解析的字符串中没有确定时区的字符串。它的10-26-2011 10:16:29不是“10-26-2011 10:16:29 CET”你解决了我的问题,我可以只
    “09-19-2012 11:08:44”+“CST”
    。我认为你的答案是正确的。那么当你进入夏令时呢?这个+CST不应该被告知更多吗?根据上面的评论,如果我们能根据刚格式化的时间来选择,那就太好了。。。我正在学习讨厌时区。如果你在一个有CEST/CET时区的国家,固定的偏移量是不起作用的。我也对此感兴趣,我不知道如何对当前时区进行strtime解析(但不是现在的值,正确的值取决于解析的字符串)。这个答案不正确
    parse()
    不使用
    time\u类
    选项。它直接设置在
    Chronic
    类上。这将最终改变慢性病的未来版本,尽管我的坏。。。我将删除,直到此选项可用=)呃。。。我无法删除已接受的答案。我将在上面发表评论。方法已折旧对不起:(这使用机器的时区,而不是Rails中设置的时区,顺便说一句@Sean Yes,这是正确的。解决方法是对Rails 5+或对旧版本的Rails使用Time.zone.strtime.local_to_utc(DateTime.strtime('12/28/2016 5:00 PM','%m/%d/%Y%H:%m%p'))
    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)