Breaking a string into smaller chunks - ruby

I have this string s that is formatted in this way. I want to turn it into a Time object.
Here is my attempt at doing this and making it readable.
s = "15081992"
n = { :year=> s[4..7], :month=> s[2..3], :day=> s[0..1] }
newtime = Time.mktime( n[:year], n[:month], n[:day] )
# 1992-08-15 00:00:00 -0400
It works, but I'm seeking any suggestion or feedback on how to write this in a better way to achieve the same result or is this pretty much it?

require 'date'
Date.strptime("15081992", "%d%m%Y")

Related

Make time stamp from string

I need to format 161901 to 04:19:01PM.
I tried the following:
Time.parse(161901)
"161901".chars.each_slice(2).map(&:join)
Time.parse("161901".chars.each_slice(2).map(&:join))
Being a newbie to ruby, it is difficult to find a way.
Here's is the most basic answer, but it makes some assumptions:
require 'time'
time = Time.strptime('161901', '%H%M%S')
time.strftime('%I:%M:%S%p')
=> "04:19:01PM"
The issue is that your string '161901' may or may not be padded and it might also be an integer and not a string. For example, if the time was 6:00 am, perhaps you get a string such as: '60000', you would need to pad this on the left hand side to parse this properly. Due to this I would suggest the following approach:
require 'time'
# Assume your time is an integer with no right padding:
time = 61901
ptime = Time.strptime(time.to_s.rjust(6, '0'), '%H%M%S') # Do proper padding
ptime.strftime('%I:%M:%S%p')
=> "06:19:00AM"
This should help sanitize your variable that you are parsing to produce consistent results.
References: https://ruby-doc.org/stdlib/libdoc/date/rdoc/DateTime.html#method-i-strftime
DateTime::strptime and DateTime#strftime are purpose-built for this task.
require 'time'
fmt_in = '%H%M%S'
fmt_out = '%I:%M:%S%p'
t = DateTime.strptime('161901', fmt_in)
t.strftime(fmt_out)
#=> "04:19:01PM
You can do like below it was very easy for use multiple times with environment variables if you have fixed display format for time
require 'time'
class Time
def self.strpftime(str, in_format,
out_format = ENV.fetch('out_format'))
strptime(str, in_format).strftime(out_format)
end
end
# with out using environment variable
Time.strpftime('161901', '%H%M%S', '%I:%M:%S%p')
=> "04:19:01PM"
# using environment variable
Time.strpftime('161901', '%H%M%S')
=> "04:19:01PM"
You'll be best off using "strptime" when converting strings to dates or times.
https://ruby-doc.org/stdlib-2.4.1/libdoc/time/rdoc/Time.html#method-c-strptime :
2.5.8 :006 > Time.strptime("161901","%H%M%S")
=> 2020-12-18 16:19:01 +0000
this will get you a "Time" object that you'll be able to query, parse, sort and/or output in different format.
require 'time'
input = '161901'
formatted_input = input.split('').each_slice(2).to_a.map(&:join).join(':')
time = Time.parse(formatted_time)
formatted_time = time.strftime("%I:%M:%S%p")
Output:
=> "04:19:01PM"

Compare hash values with String

I want to compare values from hash and Sting.
successful_response = {
'00' => { error_message: 'TESTMODE: No real money will be transferred!'}
}
if error = successful_response[response_code]
if successful_response[response_code] != current_technical_message
raise "\n\nWrong tecnical message for code #{response_code}. It should be #{successful_response[response_code]}"
end
else
UnknownResponseError.new(technical_message, response_code)
end
Every time I error. Looks like this is not the proper way to compare the values successful_response[response_code] and current_technical_message
When I print the values I get
{:error_message=>"TESTMODE: No real money will be transferred!"} and
TESTMODE: No real money will be transferred!
What is the proper way to compare them?
Your problem is that successful_response[response_code] points at another hash. The easiest — but potentially error-prone — way to fix your problem is to use the following:
successful_response[response_code][:error_message]
If you Ruby version is new enough, Hash#dig is a good alternative:
successful_response.dig(response_code, :error_message)

Decompress delta compressed sequence of numbers in Scala

Yesterday, I asked about From a List representation of a Map, to a real Map in Scala
After few really smart response, I know that it is necessary change my mind to work in Scala and I am sure that stackoverflow is the way.
In this occasion, I want to decompress a sequence of number stored using delta compression.
I think that my implementation is really simple, but I am sure that you guys are going to find other more functional way.
def deltaDecompression(compressed : Seq[Long]) = {
var previous = 0L
compressed.map(current => {
previous += current
previous
})
}
assert(deltaDecompression(Seq(100,1,2,3)) == Seq(100,101,103,106))
So like in my previous question, the question is: Is possible to implement this function using a more functional way?
Example input data and expected output in the last line of the code, as an assertion.
compressed.scanLeft(0l) { _ + _ }.drop(1)

How can I calculate the number of weeks since a given date in Ruby?

Objective
I am trying to calculate the distance in weeks since a given date without jumping through hoops. I'd prefer to do it in plain Ruby, but ActiveSupport is certainly an acceptable alternative.
My Code
I wrote the following, which seems to work but looks like the long way around to me.
require 'date'
DAYS_IN_WEEK = 7.0
def weeks_since date_string
date = Date.parse date_string
days = Date.today - date
weeks = days / DAYS_IN_WEEK
weeks.round 2
end
weeks_since '2015-06-15'
#=> 32.57
ActiveSupport's #weeks_since takes a number of weeks as its argument, so it doesn't fit this use case. Ruby's Date class doesn't seem to have anything relevant, either.
Alternatives?
Is there a better built-in solution or well-known algorithm for calculating the number of weeks separating a pair of dates? I'm not trying to code-golf this, as readability trumps brevity, but simply to learn whether Ruby natively supports the type of date arithmetic I've coded by hand.
require 'date'
str = '2015-06-15'
Date.parse(str).step(Date.today, 7).count # => 33
Date.parse(str).upto(Date.today).count.fdiv(7).round(2) # => 32.71
Might be easier to convert the dates to time and then divide the time difference by a week. You can round it however you want or ceil.
def weeks_since(date_string)
time_in_past = Date.parse(date_string).to_time
now = Time.now
time_difference = now - time_in_past
(time_difference / 1.week).round(2)
end
in_weeks (Rails 6.1+)
Rails 6.1 introduces new ActiveSupport::Duration conversion methods like in_seconds, in_minutes, in_hours, in_days, in_weeks, in_months, and in_years.
As a result, now, your problem can be solved as:
date_1 = Time.parse('2020-10-18 00:00:00 UTC')
date_2 = Time.parse('2020-08-13 03:35:38 UTC')
(date_2 - date_1).seconds.in_weeks.to_i.abs
# => 9
Here is a link to the corresponding PR.

iterate an array of strings and perform a regexp

Given an array of DateTime Strings, I want to just fetch the times e.g. 10:30:00.
So far I come up with this, but it wont give me the right result:
["2011-07-30 10:00:00","2011-07-30 12:00:00"].each{|item| item.match(/\d{2}:\d{2}:\d{2}/)}
If all the strings really are like that then just do some substring mangling:
a = ["2011-07-30 10:00:00","2011-07-30 12:00:00"]
times = a.map { |e| e[11,8] }
This will also work if your timestamps include things like 2011-07-30 10:00:00.1123, 2011-07-30T10:00:00, or 2011-07-30 10:00:00 +0700.
If you wanted to be friendlier to the future, then you could do this:
off = '9999-99-99 '.length
len = '99:99:99'.length
times = a.map { |e| e[off, len] }
so no one would have to guess what the 11 and 8 were all about.
You could achieve the same using the excellent DateTime library from Ruby.
require 'date'
["2011-07-30 10:00:00","2011-07-30 12:00:00"].map{|item|
DateTime.parse(item).strftime("%H:%M:%S")
}
=> ["10:00:00", "12:00:00"]
Though, mu's answer is great.

Resources