Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/61.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.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 解析JSON日期时间?_Ruby On Rails_Ruby On Rails 3 - Fatal编程技术网

Ruby on rails 解析JSON日期时间?

Ruby on rails 解析JSON日期时间?,ruby-on-rails,ruby-on-rails-3,Ruby On Rails,Ruby On Rails 3,我使用的JSON API以字符串形式返回日期时间值,格式如下: /日期(1370651105153)/ 如何将这样的值解析为rails中的datetime变量?整数似乎是unixtime(以毫秒为单位)。只需将最后三位数字剪掉,然后将其余的数字输入到时间。在: Time.at(1370651105) # => 2013-06-08 04:25:05 +0400 这似乎是一个UNIX时间戳(自纪元起的秒数)。此外,它似乎是从历元开始的毫秒 因此,您可以像这样转换它-假定value是一个如下

我使用的JSON API以字符串形式返回日期时间值,格式如下:

/日期(1370651105153)/


如何将这样的值解析为rails中的datetime变量?

整数似乎是unixtime(以毫秒为单位)。只需将最后三位数字剪掉,然后将其余的数字输入到
时间。在

Time.at(1370651105) # => 2013-06-08 04:25:05 +0400

这似乎是一个UNIX时间戳(自纪元起的秒数)。此外,它似乎是从历元开始的毫秒

因此,您可以像这样转换它-假定
value
是一个如下所示的字符串:

value = "/Date(1370651105153)/"

if value =~ /\/Date\((\d+)\)\//
  timestamp = $1.to_i
  time = Time.at(timestamp / 1000)
  # time is now a Time object
end

您需要除以1000,因为
Time#at
希望它的参数是秒,而不是从纪元开始的毫秒。

对于任何需要包含时区的更健壮解决方案的人,这是我提出的解析器:

def parse_json_datetime(datetime)
  # "/Date(-62135575200000-0600)/" seems to be the default date returned if the value is null
  if datetime == "/Date(-62135575200000-0600)/"
    # return nil because it is probably a null date that is defaulting to 0.
    # to be more technically correct you could just return 0 here if you wanted.
    return nil
  elsif datetime =~ /\/Date\(([-+]?\d+)(-+\d+)?\)\// # parse the seconds and timezone (if present)
    milliseconds_since_epoch = $1
    time = Time.at(milliseconds_since_epoch.to_i/1000.0).utc # divide by 1000 because it is in milliseconds and Time uses seconds

    if timezone_hourly_offset = $2
      timezone_hourly_offset = timezone_hourly_offset.gsub("0","").to_i
      time = time+(timezone_hourly_offset*60*60) # convert hourly timezone offset into seconds and add onto time
    end
    time
  else
    raise "Unrecognized date format."
  end
end

andyisnowskynet的答案()中有一些错误:有一个小的RegEx错误,这意味着它不会检测到正时区;而且它不支持
-0430
()等。另外,它返回的
Time
对象可以进行适当的Ruby时区处理,而不是添加时间偏移量,这是更传统的方法

这是我对这个答案的改进版本

首先,对于以这种格式表示的日期时间值,时间序列部分(例如,OP示例中的
1370651105153
)始终是自
1970-01-01 00:00:00 GMT
以来的毫秒数,不受时区后缀的存在或不存在的影响。因此,作为字符串的一部分包含的任何时区都不会改变它所代表的历史点。它仅用于说明“观察者”当时所在的时区

Ruby
Time
对象能够处理这两条信息(即实际日期时间“值”和时区“元数据”)。证明:

a=时间(-1).utc
#=>1969-12-3123:59:59 UTC
b=时间点(-1).getlocal('+09:30')
# => 1970-01-01 09:29:59 +0930
a==b
#=>正确
如您所见,尽管两者看起来像不同的值(由于它们在不同的时区中表示),但
=
相等运算符显示它们实际上引用了相同的时间点

知道了这一点,我们可以对
parse_json_datetime
进行如下改进(同时纠正其他错误):

def parse_json_datetime(datetime)
#“/Date(-62135575200000-0600)/”似乎是返回的默认日期
#如果该值为空:
如果datetime==“/日期(-62135575200000-0600)/”
#返回nil,因为它可能是默认为0的空日期。
#为了在技术上更准确,如果需要,您可以在此处返回0:
归零
elsif datetime=~%r{/Date\([-+]?\d+([-+]\d+)/}
#我们现在已将字符串解析为:
#-$1:自1970年1月1日以来的毫秒数。
#-$2:[可选]时区偏移。
#将$1除以1000,因为它以毫秒为单位,时间使用秒:
自新纪元起的秒数=$1.0到\u i/1000.0
时间=时间.at(从时间到时间的秒数)。utc
#我们现在有了这代表的确切历史时刻,
#存储为基于UTC的“时间”对象。
如果2美元
#我们有一个时区,所以转换它的格式(添加冒号)。。。
时区=$2.gsub(/(…)(…)/,“\1:\2”)
#…然后将其应用于时间对象:
time=time.getlocal(时区)
结束
时间
其他的
引发“无法识别的日期格式”
结束
结束
然后我们可以测试:

#参见:http://momentjs.com/docs/#/parsing/asp-净json日期/
解析日期时间(“/Date(1198908717056-0700)/”)
# => 2007-12-28 23:11:57 -0700
#纪元前1分钟,但在ACST中:
解析日期时间(“/Date(-60000+0930)/”)
# => 1970-01-01 09:29:00 +0930
#同上,但自然转换为UTC等效值:
解析日期时间(“/Date(-60000+0930)/”)。utc
#=>1969-12-3123:59:00UTC
#同上,未指定时区(表示UTC):
解析日期时间(“/Date(-60000)/”)
#=>1969-12-3123:59:00UTC
#OP的例子:
解析日期时间(“/Date(1370651105153)/”)
#=>2013-06-08 00:25:05 UTC
#同上,但在两个不同的时区中说明:
aaa=parse_json_datetime(“/Date(1370651105153-0200)/”)
# => 2013-06-07 22:25:05 -0200
bbb=parse_json_datetime(“/Date(1370651105153-0800)/”)
# => 2013-06-07 16:25:05 -0800
#作为“渲染”字符串,它们不相同:
aaa.to_s==bbb.to_s
#=>错误
#但作为时间的瞬间,它们是等价的:
aaa==bbb
#=>正确
#为了论证,如果它们都在
#相同的时区(在本例中为任意“-04:00”),然后它们也会渲染
#作为相等字符串:
aaa.getlocal('-04:00')。to_s==bbb.getlocal('-04:00')。to_s

这将输出:

{"hi"=>Mon, 10 Aug 2009 15:01:02 EDT -04:00}
打开
ActiveSupport.parse_json\u times
标志后,您解码的任何json有效负载都会自动转换为
ActiveSupport::TimeWithZone
对象

积极支持。您可以很好地了解它支持的时间格式。看起来它支持ISO 8601,但不支持Unix/POSIX/Epoch时间戳

在创建时,我在Active Support中了解到了此功能

{"hi"=>Mon, 10 Aug 2009 15:01:02 EDT -04:00}