ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Can anyone tell me how I can compare two dates in an array? I have about 12,000 records that I need to compare to see if any of the times have overlapped by a specified time range.
Example:
If I have a list of dates that are like the following:
1/3/06 12:25
1/3/06 13:06
I want to be able to specify if they have overlapped by specifying a specific time range, be it 5 minutes or 1 minute or an hour.
Is there a way to do this? Right now I have just parsed the code to get it into a time/date format.
Code:
require 'parsedate'
dates_array = []
new_date_array = []
p 'Insert dates into the array'
date_input = gets.chomp
while (date_input !="")
dates_array[dates_array.length]=date_input
date_input=gets.chomp
end
p dates_array.index(dates_array.last)
p ''
dates_array.each do |date|
p ParseDate.parsedate(date)
end
p ''
p 'End'
The most efficient way to do it (that I can think of off the top of my head) is to maintain a queue of times which overlapped with the previously-read time. The head of this queue is the furthest-away time you have to check for overlap with the time you read next. This assumes that you're reading the times in order, or that you've read them all in and sorted them. In other words, if time(n) didn't overlap with time(m), it won't overlap with time(m+1). After you've decided the times which overlap with the one you just read in, you push that new one onto the queue.
Here's some code:
Code:
require 'parsedate'
times = ["1/3/06 12:25", "1/3/06 13:06", "1/3/06 13:07"]
queue = []
times.each do | time |
time = ParseDate.parsedate(time)
time = Time.local(*time)
while not queue.empty? and (time - queue.first).abs > 300
queue.shift
end
if not queue.empty? then
puts time.to_s + ' overlaps with ' + queue.first.to_s +
' by ' + (time - queue.first).abs.to_s
else
puts time.to_s + ' does not overlap with any other time.'
end
queue.push time
end
When two times overlap, I print out the earliest overlapped time and the amount of overlap. The magical 300 number in the while loop is the maximal amount of time you accept as overlap in seconds -- in this version, time entries less than five minutes apart are considered overlapping.
It looks like this might not be such a good idea. I am dealing with a years worth of records so we are talking something in the several thousands. Its probably better if I can find a way to show an overall date and time and how many other records overlap with that date. This makes it so that I don't have to show as many records.
example:
Date: 2/28/2007 Time: 13:00:00 Number of calls: 2
Date: 2/28/2007 Time: 15:00:00 Number of calls: 7
Just a thought, but might it be simpler to convert the time/dates into "seconds since epoch" format, and then just compare them as integers (which is pretty quick).
If you are building an array, you can perform the conversion as the items go into the array. I use something similar in a C project with a list of timed events.
With a little help from one of my database developers(who went to ruby training), I was able to get this the way I wanted. Here's the code we put together.
Code:
#!/usr/bin/ruby -w
require 'FileUtils'
require 'time'
input_array=[]
attendee_array=[]
time_array=[]
count_array=[]
attendee_count_array=[]
# Read in dates file
File.open("overalldates.txt","r") do |ofile|
while(line = ofile.gets )
input_array << line.split(",")
end
end
# Read in attendees file
File.open("attendees.txt","r") do |alist|
while(line2 = alist.gets)
attendee_array << line2.to_i
end
end
time=''
input_array.each_index do |each_time_string|
# Create Time array from the input array
time_array.push(Time.local(input_array[each_time_string][0],input_array[each_time_string][1],input_array[each_time_string][2],input_array[each_time_string][3],input_array[each_time_string][4],input_array[each_time_string][5]))
end
time_array.each_index do |each_time_element|
count = 0
attendee_count = attendee_array[each_time_element]
time_array.each_index do |each_inner_time_element|
if each_time_element != each_inner_time_element && time_array[each_time_element] < time_array[each_inner_time_element]
if (time_array[each_time_element]+60*60 <= time_array[each_inner_time_element]) == false
count+=1
attendee_count+=attendee_array[each_inner_time_element]
end
end
end
count_array.push(count)
attendee_count_array.push(attendee_count)
end
#
time_array.each_index do |array_elem|
File.open "outputfile.txt", 'a' do |file|
file.write "#{time_array[array_elem]}, #{count_array[array_elem]}, #{attendee_count_array[array_elem]}"+"\r"
end
end
p "File Complete"
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.