Ruby on rails 解析JSON日期时间?
我使用的JSON API以字符串形式返回日期时间值,格式如下: /日期(1370651105153)/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是一个如下
如何将这样的值解析为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
以来的毫秒数,不受时区后缀的存在或不存在的影响。因此,作为字符串的一部分包含的任何时区都不会改变它所代表的历史点。它仅用于说明“观察者”当时所在的时区
RubyTime
对象能够处理这两条信息(即实际日期时间“值”和时区“元数据”)。证明:
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}