Ruby: How to check if date and time are within a range - ruby

I'm trying to create a method to determine whether or not a particular date and time (within a certain timezone) are within a range.
range = between(start_time, end_time)
start_time = "date time timezone"
end_time = "date time timezone"
Here's an example of what the range input will look like:
range => between("2013-12-25 04:45:00 -0800", "2015-12-25 5:00:01 -0800")
I want to return true or false if a particular date and time falls within this range.
Example particular date:
instance = "2014-01-01 16:35:45 -0800"
instance.between("2013-12-25 04:45:00 -0800", "2015-12-25 5:00:01 -0800")
I don't have much experience with time in Ruby. Any suggestions would be greatly appreciated.

require "date"
instance = DateTime.parse("2014-01-01 16:35:45 -0800")
d1 = DateTime.parse("2013-12-25 04:45:00 -0800")
d2 = DateTime.parse("2015-12-25 5:00:01 -0800")
p instance.between?( d1, d2 ) # => true

Related

How to obtain first date of each month based on given year range in Nifi flow

I would like to know what could be the best way to obtain the starting date values for each month based on the date range.
For example: If I am given a year range of 2015-11-10 and 2018-01-15(format YYYY-mm-dd). Then I would like to extract following dates:
2015-12-01
2016-01-01
.
.
2018-01-01
You can try to use this flow for generating the first day of each month in the provided date range.
Overall flow
Step 1 Configuration: Start
Step 2 Configuration: Configure Date Range
Provide the start and end dates as configuration parameters via this step.
Step 3 Configuration: Generate First Dates For Months
This uses a Groovy script, which is provided below
Groovy script
flowFile = session.get();
if(!flowFile)
return;
DATE_FORMAT = 'yyyy-MM-dd';
startDate = Date.parse(DATE_FORMAT, flowFile.getAttribute("start_date"));
endDate = Date.parse(DATE_FORMAT, flowFile.getAttribute("end_date"));
allFirstDates = "";
Calendar calendar = Calendar.getInstance();
Set firstDaysOfMonths = new LinkedHashSet();
for (int i = 0; i <= endDate-startDate; i++) {
calendar.setTime(startDate.plus(i));
calendar.set(Calendar.DAY_OF_MONTH, 1);
firstDayOfMonth = calendar.getTime();
if (firstDayOfMonth.compareTo(startDate) >= 0) {
firstDaysOfMonths.add(calendar.getTime().format(DATE_FORMAT));
}
}
firstDaysOfMonths.each {
firstDayOfMonth -> allFirstDates = allFirstDates + firstDayOfMonth + "\n";
}
flowFile = session.putAttribute(flowFile,"all_first_dates", allFirstDates );
session.transfer(flowFile,REL_SUCCESS)
Step 4 Configuration: View Result
Output of run:
When the flow is run, the attribute all_first_dates will be populated with the first dates of each month in the date range.

Subtract Time from CSV using Ruby

Hi I would like to subtract time from a CSV array using Ruby
time[0] is 12:12:00AM
time[1] is 12:12:01AM
Here is my code
time_converted = DateTime.parse(time)
difference = time_converted[1].to_i - time_converted[0].to_i
p difference
However, I got 0
p time[0].to_i gives me 12
is there a way to fix this?
You can use Time#strptime to define the format of the parsed string.
In your case the string is %I:%M:%S%p.
%I = 12 hour time
%M = minutes
%S = seconds
%p = AM/PM indicator
So to parse your example:
require 'time'
time = %w(12:12:00AM 12:12:01AM)
parsed_time = time.map { |t| Time.strptime(t, '%I:%M:%S%p').to_i }
parsed_time.last - parsed_time.first
=> 1
Use the Ruby DateTime class and parse your dates into objects of that class.

How to use date helper in CodeIgniter to find time conflict?

I have a database table
TABLE subject_loads
id (int)
subject_name (varchar)
time_start (time)
time_end (time)
time_diff (decimal)
When I save it on database, it will first check whether the time is not conflicting from the other time already inputed. If it's okay, then compute the time_start and time_end to give me a difference between the two.
Example, 7:30 AM - 8:30 AM is already in database, when i input 8:00 AM - 9:00 AM it will say "conflicting with the other time". Only I can input before 7:30 AM or after 8:30 AM that doesn't overlap from 7:30 AM - 8:30 AM.
Can someone help on how to do this?
First you need to check if overlapping values (compared to new value) already exist. You will do that with:
$query = $this->db->get_where('subject_loads', array('time_start >= ' => $time_start, 'time_end <= ' => $time_end));
if((int)$query->num_rows() > 0)
{
//similar values exist
}
else
{
//you are free to insert values
}
Second part of issue:
$hm1 = "2:12 AM";
$hm2 = "4:41 PM";
$e = conv($hm2) - conv($hm1);
echo $e;
function conv($time)
{
$expl_time = explode(' ', $time);
$t = explode(":", $expl_time[0]);
if ($expl_time[1] == 'PM' || $expl_time[1] == 'pm')
{
$t[0] += 12;
}
return ($t[0] + round($t[1]/60, 1, PHP_ROUND_HALF_UP));
}

Nicest way to turn "2015-03-18 22:00" into a Time object

I have three strings, pulled from a database:
"2015-03-18" (the date the event occurs)
"22:00" (the hour an event occurs)
"-05:00" (the UTC offset in the location the event occurs).
I want to combine these three strings to produce a Ruby Time object. I'm doing:
utc_offset = "-05:00"
airtime = "22:00"
airday = "2015-03-18"
year,month,day,hour,minutes = airday.split("-").map(&:to_i) + airtime.split(":").map(&:to_i)
Time.new(year,month,day,hour,minutes,0,utc_offset)
This works; I'm just wondering if it's the correct/standard/idiomatic/clearest way.
By using Time.parse
When ‘time’ is required, Time is extended with additional methods for
parsing and converting Times.
require 'time'
utc_offset = "-05:00"
airtime = "22:00"
airday = "2015-03-18"
time = Time.parse("#{airday} #{airtime} #{utc_offset}")
I think this is the way to do it.
Time.new(*airday.split("-"), *airtime.split(":"), 0, utc_offset)
How about this? http://ruby-doc.org/stdlib-2.1.5/libdoc/time/rdoc/Time.html#method-c-strptime
require 'time'
raw_time = '2015-03-18 22:00'
parsed_time = Time.strptime(raw_time, '%Y-%m-%d %H:%M') # 2015-03-18 22:00:00 +0100

Ruby - Merge 2 arrays of objects and group by one attribute and sum the rest

Given I have 2 arrays that contain objects. On those objects there is an datetime attribute and a fixed number of metrics. What I need to do is merge the two arrays and sum the metrics by the datetime.
Array 1:
#<ReadingsProvider::Reading:0x007fc52dd5a0a8 #start_date=2012-12-09 03:00:00 UTC, #item1=13, #item2=46, #item3=6, #item4=4, #item5=9, #item6=17, #item7=34>,
#<ReadingsProvider::Reading:0x007fc52dbd54d0 #start_date=2012-12-09 04:00:00 UTC, #item1=43, #item2=90, #item3=7, #item4=4, #item5=9, #item6=17, #item7=34>,
Array 2
#<ReadingsProvider::Reading:0x007fc52db95f88 #start_date=2012-12-09 03:00:00 UTC, #item1=23, #item2=16, #item3=5, #item4=6, #item5=8, #item6=20, #item7=36>,
#<ReadingsProvider::Reading:0x007fc52db591f0 #start_date=2012-12-09 04:00:00 UTC, #item1=76, #item2=12, #item3=6, #item4=5, #item5=10, #item6=17, #item7=33>
Final Array (assuming my by hand math is right...)
#<ReadingsProvider::Reading:0x007fc52db95f88 #start_date=2012-12-09 03:00:00 UTC, #item1=36, #item2=62, #item3=11, #item4=10, #item5=17, #item6=37, #item7=70>,
#<ReadingsProvider::Reading:0x007fc52db591f0 #start_date=2012-12-09 04:00:00 UTC, #item1=119, #item2=102, #item3=13, #item4=9, #item5=19, #item6=34, #item7=67>
What I ended up doing... needs testing to make sure it's working as expected.
def merge_arrays(array1, array2)
result = array1.concat(array2).group_by(&:start_date).map do |date, array|
my_hash = {
start_date: date,
item1: array.map(&:item1).inject(:+),
item2: array.map(&:item2).inject(:+),
item3: array.map(&:item3).inject(:+),
item4: array.map(&:item4).inject(:+),
item5: array.map(&:item5).inject(:+),
item6: array.map(&:item6).inject(:+),
item7: array.map(&:item7).inject(:+)
}
ReadingsProvider::Reading.new(my_hash)
end
result
end
Specific task, but I try to write some code.
At first, include method to ReadingsProvider::Reading
def concat_with(another)
if #reading_start_date == another.instance_variable_get(:#reading_start_date)
instance_variables.each do |var|
if var.to_s.include?("item") && another_value = another.instance_variable_get(var)
another.instance_variable_set(var, another_value + instance_variable_get(var))
end
end
end
end
Then general approach:
array1.map do |reading|
array2.map do |another|
reading.concat_with(another)
end
end.flatten.compact
If i'd know more, the code should be more elegant anyway. This code looks ugly.

Resources