sorting while or after merging hashes, in ruby - ruby-on-rails

i have a hash thats looks like
myhash = [{"project 1"=>{"09 Apr 12, Mon"=>"2.75"}}, {"project 1"=>{"11 Apr 12,
Wed"=>"3.200000047683716"}}, {"project 1"=>{"25 Apr 12, Wed"=>"0.5099999904632568"}},
{"project 1"=>{"31 May 12, Thu"=>"1"}}, {"project 1"=>{"01 Jun 12, Fri"=>"1"}}, {"project
2"=> {"01 Jun 12, Fri"=>"0"}}, {"project 1"=>{"04 Jun 12, Mon"=>"0.25"}}]
I want to merge internal hashes based on their keys. such that keys are not duplicated
I tried,
myhash.inject{|memo, el| memo.merge( el ){|k, old_v, new_v| old_v.merge(new_v)}}
which is giving correct results
=>{"project 2"=>{"01 Jun 12, Fri"=>"0"}, "project 1"=>{"01 Jun 12, Fri"=>"1", "09 Apr
12, Mon"=>"2.75", "11 Apr 12, Wed"=>"3.200000047683716", "31 May 12, Thu"=>"1", "25 Apr
12, Wed"=>"0.5099999904632568", "04 Jun 12, Mon"=>"0.25"}}
but the order is lost. how to sort above hash on the basis of dates that are keys inside the hashes.
or at the time of merging itself order is maintained.
I am using ruby 1.8.7

This should do it. Note that I've parsed the dates in order to sort them. It should be trivial to get them back to your original format. merged is the merged unordered hash you provided.
merged.map{|k,v| { k => v.sort_by{|d,f| Date.strptime(d.split(',')[0],"%d %b %y").to_s } } }
You might want to think about using Date objects and an array rather than a hash, which (in 1.8.7 at least) is unordered.

Related

How to configure Jenkins job to run every 45 minutes?

I am trying to configure a Jenkins job to run every 45 minutes:
*/45 * * * *
But the latest intervals of the running job don't look fine to me ever since I changed it:
Mar 27, 2020 11:45 AM
Mar 27, 2020 11:00 AM
Mar 27, 2020 10:45 AM
Mar 27, 2020 10:00 AM
Mar 27, 2020 9:45 AM
Mar 27, 2020 8:36 AM
Mar 27, 2020 7:36 AM
Mar 27, 2020 6:36 AM
As you can see, before changing the interval, the job ran once every hour.
I actually expected the output to be like this:
Mar 27, 2020 12:45 AM
Mar 27, 2020 12:00 AM
Mar 27, 2020 11:15 AM
Mar 27, 2020 10:30 AM
Mar 27, 2020 9:45 AM
What's wrong with my configuration?
You are running your job every 45 minutes within an hour. Each hour is handled separately and counter starts over.
Simplest fix is to change interval to hour or 30 minutes (in general to something that divides an hour without reminder) - this way you'll have even intervals without extra effort. Con is obvious - frequency is not exactly what you wanted.
Other way is to set intervals to smaller value (like 15 minutes) and check time in job (and exit job if time didn't pass yet). Con is that you need extra logic in job and that you have "empty" builds in history.
Last option is to set every trigger manually - 32 triggers a day for "every 45 minutes". It can be quite compact for some intervals (like 45 minutes), but in case you wanted to change it to "every 41 minutes" it becomes a mess.

Ruby parse DateTime with variable

I'm trying to parse a specific hour of a specific date. When I put the date directly as an argument, it works fine, but when I create a variable and put it in the argument it returns the current date.
Why is that?
NOTE: the variable time is 9pm and I need to parse 9pm of 12 March 2016.
datetime = DateTime.new(2016,3,12,9)
=> Sat, 12 Mar 2016 09:00:00 +0000
DateTime.parse("sat 12 march 2016 9pm")
=> Sat, 12 Mar 2016 21:00:00 +0000
DateTime.parse("datetime 9pm")
=> Mon, 14 Mar 2016 21:00:00 +0000
In your third call, you use the literal string "datetime" rather than the value of your datetime variable. You can use string interpolation to use the variable's value:
DateTime.parse("#{datetime} 9pm")
In this case, the "9pm" is ignored since it doesn't make sense added to the end of an existing date but this is why the initial attempt wasn't working. Interpolation is generally a solution for using a variable's value rather than its name.
If your goal is to change the time of an existing date, use the change method:
datetime.change(hour:21)
You can also try this
date = Date.new(2016,3,12)
DateTime.parse("#{date} 9pm")
## Output
Sat, 12 Mar 2016 21:00:00 +0000
OR
datetime = DateTime.new(2016,3,12,9)
DateTime.parse((datetime + 12.hours).to_s)
## Output
Sat, 12 Mar 2016 21:00:00 +0000
OR
DateTime.parse((datetime + 12.hours).to_s).strftime("%a, %d %b %Y %I:%M %p")
## Output
Sat, 12 Mar 2016 09:00 PM

Rails: Calculate how many days are overlapped between 2 date ranges

okay, lets say we have three date ranges.
1. date1=01-20-2015..02-15-2015
2. date2 = 01-01-2015..01-31-2015
3. date3 = 02-01-2015..02-28-2015
I need a way to calculate how many days between date1 and date2 are overlapped (10 days in this case).
and how many days between date1 and date3 are overlapped (15 days in this case)?
Is there a easy way to calculate this?
If you have:
r1= (Date.new(2015, 01, 20))..(Date.new(2015, 2, 15))
r2= (Date.new(2015, 01, 1))..(Date.new(2015, 1, 31))
You can check the intersection this way:
r1.to_a & r2.to_a
=> [Tue, 20 Jan 2015,
Wed, 21 Jan 2015,
Thu, 22 Jan 2015,
Fri, 23 Jan 2015,
Sat, 24 Jan 2015,
Sun, 25 Jan 2015,
Mon, 26 Jan 2015,
Tue, 27 Jan 2015,
Wed, 28 Jan 2015,
Thu, 29 Jan 2015,
Fri, 30 Jan 2015,
Sat, 31 Jan 2015]
The cost is to convert ranges to arrays though
You can notice (r1.to_a & r2.to_a).count #=> 12, not 10 but well depends whether or not you include boundaries.

Should ActiveSupport::TimeWithZone (and Time.zone)'s methods respect DST changes?

Look at this code:
[4, 5, 6, 7].each do |x|
start_at = Time.zone.parse("2014.10.2#{x} 08:00")
puts "#{start_at.inspect} / #{start_at.seconds_since_midnight/60}"
end
Output:
Fri, 24 Oct 2014 08:00:00 CEST +02:00 / 480.0
Sat, 25 Oct 2014 08:00:00 CEST +02:00 / 480.0
Sun, 26 Oct 2014 08:00:00 CET +01:00 / 480.0
Mon, 27 Oct 2014 08:00:00 CET +01:00 / 480.0
We are in Germany, and on October 26 the DST is reset so 08:00 is not actually 8*60 minutes since midnight but 9*60.
IMHO, this should be respected by the seconds_since_midnight method. Am I missing something or is this actually a Ruby bug?
Using Ruby 1.9.3, Rails 3.0.20 on Mac OS X 10.9.5 (MacPorts).
(Yes, Rails 3.0.20 is old. Legacy project. If it's fixed in Rails 4, all the better.)
According to the Rails docs, it's implemented as such:
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 14
def seconds_since_midnight
sec + (min * 60) + (hour * 3600)
end
Thus, this function is not time zone aware. It simply looks at the local time value. It does not consider that the offset of midnight might not be the same as the offset of the value you provided. Nor does it consider that midnight might not exist in the local time zone (such as with Brazil's spring-forward transition).
Is this a bug? Perhaps. But one might also say the method is just poorly named. Either way, it's an issue with Rails, not with Ruby.

Erlang - How Can I Parse RFC1123 Dates Into An Erlang Term?

Without using a third party module, what steps would I need to take to convert this:
<<"Mon, 17 Feb 2014 11:07:53 GMT">>
Into this?:
[17, 2, 2014, 10, 07, 53]
Most of the answers I've Googled suggest using a library.
So far, I suspect I'd get somewhere by pattern matching the formatted date string.
Something like:
<<_:5/binary, Date:2/binary>> = <<"Mon, 17 Feb 2014 11:07:53 GMT">>...
Which I think should produce the following 'match'
Date = 17...
That's based on an idea found here - https://groups.google.com/forum/#!topic/erlang-programming/OpXSqt3U86c - Is this a good approach?
Are there any BIF's or modules that can help with this?
And furthermore, how would I convert/map "Feb" to an integer?
Let's try that in the shell:
1> <<_:5/binary, Date:2/binary>> = <<"Mon, 17 Feb 2014 11:07:53 GMT">>.
** exception error: no match of right hand side value <<"Mon, 17 Feb 2014 11:07:53 GMT">>
Right, we need to match the rest of the binary at the same time:
2> <<_:5/binary, Date:2/binary, Rest/binary>> = <<"Mon, 17 Feb 2014 11:07:53 GMT">>.
<<"Mon, 17 Feb 2014 11:07:53 GMT">>
3> Date.
<<"17">>
So now Date is a binary containing the bytes for the ASCII digits 1 and 7. We can convert that to a number with binary_to_integer:
4> binary_to_integer(Date).
17
As for the conversion of month names to integers, the usual way to do something like that is with a function:
month_name_to_integer("Jan") -> 1;
month_name_to_integer("Feb") -> 2;
...
month_name_to_integer("Dec") -> 12.
You may use tempo library for datetime formatting and parsing.
Bin = <<"Mon, 17 Feb 2014 11:07:53 GMT">>,
L = binary_to_list(Bin),
{match, Res} =
re:run(L, "[0-9]+", [global, {capture, all, list}]),
[list_to_integer(X) || [X] <- Res].
the output is:
[17,2014,11,7,53]
Why suffering? Why not third party module?
I am use erlware_commons
ec_date:parse("Mon, 17 Feb 2014 11:07:53 GMT").

Resources