Rails: Grouping Hashes with same date and getting their difference - ruby-on-rails

I have 2 hases:
x = {Sun, 01 Oct 2017=>10, Wed, 01 Nov 2017=>4, Fri, 01 Dec 2017=>2}
y = {Sun, 01 Oct 2017=>7, Wed, 01 Nov 2017=>2, Fri, 01 Dec 2017=>1}
I wanted to group them and get their difference, which should produce this result:
z = {Sun, 01 Oct 2017=>3, Wed, 01 Nov 2017=>2, Fri, 01 Dec 2017=>1}

You can use reduce to achieve this, as follows:
z = x.reduce({}) do |z_hash, (key, val)|
next z_hash unless y[key]
z_hash[key] = val - y[key]
z_hash
end
Alternatively, and more built to purpose, you could use:
z = x.merge(y) { |key, v1, v2| v1 - v2 }
The first approach allows you to easily skip keys that don't appear in both hashes, while the second is what I'd recommend - merge takes an optional block for cases like this.
It's readable and gets exactly the output you'd expect.
Hope that helps - give me a shout if you've any questions :)

ar = x , y
z = p ar.inject{|memo, el| memo.merge( el ){|k, old_v, new_v| old_v - new_v}}

Related

How to calculate the sum of array inside hash ruby

Hai i am creating a json file with my data and i need to calculate the hours before i save it into the database
I am assigning that hash into a variable payload and tried doing this but it returns me an error TypeError (no implicit conversion of Symbol into Integer):
total_hours = #payload.sum{|activity| activity[:hours].to_f}
Hash before converting to json
{:activities=>
[{:project=>1,
:activity=>"my activity",
:hours=>0.2e1,
:date=>Sat, 10 Aug 2019 00:00:00 UTC +00:00},
{:project=>2,
:activity=>"Tester",
:hours=>0.2e1,
:date=>Thu, 01 Aug 2019 00:00:00 UTC +00:00},
{:project=>2,
:activity=>"Tester",
:hours=>0.3e1,
:date=>Thu, 01 Aug 2019 00:00:00 UTC +00:00}]}
I need to sum the hours of my array which is inside the hash. Thanks
If you are using Rails, here is a short way:
#payload[:activities].pluck(:hours).reduce(:+)
You should use:
total_hours = #payload[:activities].sum{|activity| activity[:hours].to_f}
You see, what you're wanting to do is, essentially:
[
{
:project=>1,
:activity=>"my activity",
:hours=>0.2e1,
:date=>Sat, 10 Aug 2019 00:00:00 UTC +00:00
},
{
:project=>2,
:activity=>"Tester",
:hours=>0.2e1,
:date=>Thu, 01 Aug 2019 00:00:00 UTC +00:00
},
{
:project=>2,
:activity=>"Tester",
:hours=>0.3e1,
:date=>Thu, 01 Aug 2019 00:00:00 UTC +00:00
}
].sum{|activity| activity[:hours].to_f}
But, you're calling .sum on the #payload variable, which is a hash. What you want is the value of the hash that is associated with the key :activities. Thus, you need to call .sum on #payload[:activities] where #payload[:activities] returns the array above.

How do I convert a `DateTime` to the corresponding date and time in Berlin?

Given a (UTC) DateTime object, how can I get the corresponding time in Berlin, in CET or CEST, depending on the date?
Examples for the desired "convert" function:
convert(DateTime.new(2018, 07))
=> Sun, 01 Jul 2018 02:00:00 +0200
convert(DateTime.new(2018, 12))
=> Sat, 01 Dec 2018 01:00:00 +0100
Try this
require 'tzinfo'
timezone = TZInfo::Timezone.get('Europe/Berlin')
local_time = timezone.utc_to_local(utc_time)
That even works without Rails.

Invalid date getting displayed in rails

I know it is common error but I could not resolve it even after trying those answers.
Through the rest api I am sending some parameters inculdes dates. I am recieving all the data in the method where I want but when I am trying to parse Date it throws error of invalid date.
Here are my parameters that I am recieving
{"uid"=>"1", "user"=>"abc.a#abc.com", "from"=>"Mon Nov 3 24:59:12 CET 2014", "to"=>"Tue Nov 11 24:59:12 CET 2014"}
and Date format is
Mon Nov 3 24:59:12 CET 2014
but it is throwing error on parsing on line below
fr = DateTime.parse(params[:from]) unless params[:from].empty?
I tried strptime as well but did not work.
Imp points is I need hour also for later processing. Thanks
what you are doing wrong is parsing DateTime while it is just date and should be parsed as one of the following ways:
1.
>> fr = params[:from].to_date unless params[:from].empty?
=> Mon, 03 Nov 2014
2.
>> fr = Date.parse(params[:from]) unless params[:from].empty?
=> Mon, 03 Nov 2014
You have 24:59 which is invalid time. Anyway, use strptime:
DateTime.strptime("Mon Nov 3 22:59:12 CET 2014", "%a %b %e %T %Z %Y")
#=> Mon, 03 Nov 2014 22:59:12 +0100

Rails - Time arithmetic

I was playing time arithmetic in rails console. I have subtracted two different times and got back a long number, please see below my code.
a = User.find(1).updated_at # returns Mon, 03 Mar 2014 11:07:43 UTC +00:00
b = User.find(1).created_at # returns Mon, 03 Mar 2014 08:36:50 UTC +00:00
a - b # returns 9053.699814796448
My question is. What is this number 9053.699814796448? Is it time? What is it's unit? and how is that calculated? Is it possible to change the default unit of the outcome?
Thanks
a - b gives you the time in seconds. Check out the Time#- .

Why does this DateTime subtraction operation return invalid results?

I have two DateTime objects, one in the past and one representing the current datetime. I am trying to find out how many minutes have passed between the two:
past = "Wed, 03 Jul 2013 00:59:39 UTC +00:00".to_datetime
now = "Wed, 03 Jul 2013 01:04:19 +0100".to_datetime
seconds = (now - past) #result is (-83/2160)
This is incorrect. Seconds should be 280, the number of seconds that have passed between the two times.
Subtracting two DateTimes returns the elapsed time in days.
So you can do:
past = "Wed, 03 Jul 2013 00:59:39 UTC +00:00".to_datetime
now = "Wed, 03 Jul 2013 01:04:19 +0100".to_datetime
seconds = (now - past) * 1.day
# => -3320.0
Or you could do:
seconds = (now.to_i - past.to_i)
# => -3320
※ The result is negative because of the Timezone.
past.utc
# => Wed, 03 Jul 2013 00:59:39 +0000
now.utc
# => Wed, 03 Jul 2013 00:04:19 +0000
You can see that now is actually older than past.

Resources