Why my test comparing times are failing sometimes? how can i improve this test?
data = { init: Time.zone.now, end: Time.zone.tomorrow }
put "/api/...", params: data,
expect(JSON.parse(response.body)['time'].to_time).to be_within(1.seconds).of(Time.zone.now)
I would like to solve this to pass always the test
Your problem is that you call Time.now multiple times and between calls, it may have changed. Better doing something like this:
now = Time.zone.now
interval = 10.seconds
data = { init: now - interval, end: now + interval }
response = put "/api/...", params: data
expect(JSON.parse(response.body)['time'].to_time).to be_within(interval).of(now)
I would also advise to compare date as integer to prevent any timezone difficulties in your test:
response_time = JSON.parse(response.body)['time']
expect(response_time.to_time.to_i).to be_within(interval).of(now.to_i)
Related
I can currently set a time range like so:
start_date: "2018-09-11"
end_date: "2018-11-19"
How can I do this for start to end of months? Examples:
time_range = ["2018-09-11".."2018-09-30"]
time_range = ["2018-10-01".."2018-10-31"]
time_range = ["2018-11-01".."2018-11-19"]
I'm not sure what's exactly your desired outcome but, given start date and end date as Date objects, you can perform
(start_date..end_date).to_a.group_by(&:month).values
and at the end what you get is a three element array, and each element contains an array with all the dates in that range for a month
I do not know if I understand very well what you asked, but I'll try to help you.
The Date class has several methods that will help you to work with dates.
Date < Object
Examples
my_date_range_array = [Date.today.beginning_of_year..Date.today.end_of_year]
my_date_time_range_array = [Time.now.beginning_of_year..Time.now.end_of_year]
my_date_range_array = [6.months.ago..Date.today]
YourModel.where date: Date.today.beginning_of_month..Date.today
YourModel.where date: 6.months.ago..Date.today
If you need every single date in the range, you can use something like this:
(Date.today.beginning_of_year..Date.today.end_of_year).map{ |date| date }
I hope that my answer helps you
This is a pure Ruby solution, but I believe (though I don't know Rails) it can be simplified slightly by replacing my methods first_day_of_month and first_day_of_month with Rails methods beginning_of_month and end_of_month, respectively. I designed the method for efficiency over simplicity.
require 'date'
DATE_FMT = "%Y-%m-%d"
def date_ranges(start_date_str, end_date_str)
start_date = Date.strptime(start_date_str, DATE_FMT)
end_date = Date.strptime(end_date_str, DATE_FMT)
return [start_date_str..end_date_str] if
[start_date.year, start_date.month] == [end_date.year, end_date.month]
d = start_date
ranges = [start_date_str..last_day_of_month(d)]
loop do
d = d >> 1
break if [d.year, d.month] == [end_date.year, end_date.month]
ranges << (first_day_of_month(d)..last_day_of_month(d))
end
ranges << (first_day_of_month(d)..end_date_str)
end
def first_day_of_month(d)
(d - d.day + 1).strftime(DATE_FMT)
end
def last_day_of_month(d)
((d >> 1)-d.day).strftime(DATE_FMT)
end
date_ranges("2018-09-11", "2019-02-11")
#=> ["2018-09-11".."2018-09-30", "2018-10-01".."2018-10-31",
# "2018-11-01".."2018-11-30", "2018-12-01".."2018-12-31",
# "2019-01-01".."2019-01-31", "2019-02-01".."2019-02-11"]
date_ranges("2018-09-08", "2018-09-23")
#=> ["2018-09-08".."2018-09-23"]
With the information provided by the OP, this is what I understand he is looking for.
Given a set range for example:
time_range = "2018-09-11".."2018-09-19"
new_range_min = time_range.min.to_date.beginning_of_month
new_range_max = time_range.max.to_date.end_of_month
new_range = new_range_min..new_range_max
I have a simple task where I want to take a starting date and an ending date and loop over the days/dates. This code is being used in my db:seed rake task. Currently, my code has gone through the following attempts.
(someModel.start_date.to_datetime..someModel.end_date.to_datetime).each {
|x| puts x
}
......
(someModel.start_date...someModel.end_date).each { |x| puts x }
In each case, I get an error like this.
can't iterate from ActiveSupport::TimeWithZone
or
can't iterate from DateTime
If anyone has any clue on how to iterate over a range of DateTimes I'd be greatly appreciative.
start = someModel.start_date.to_datetime
finish = someModel.end_date.to_datetime
while(start < finish) do
#bunch of awesome stuff
start += 1.day
end
You must make sure that you are dealing with a Date object (by calling to_date), then everything works as expected:
start_date.to_date.upto(end_date.to_date) {|date| puts date }
Or with a range:
(start_date.to_date..end_date.to_date).to_a
You can't iterate from DateTime. But you can iterate when start and end of
interval are instances of Date. Convert them if possible.
And then look at these Date methods:
step()
upto()
downto()
to use instead of each
If you want to iterate on the range you might consider a loop and step each day using something like someModel.start_date + 1.day.to_i
Here's what we're doing to iterate by minutes over two TimeWithZones:
# allow iteration over a set of TimeWithZones
def self.time_map(range, step: 30.minutes, &block)
result = []
time = range.first
max = range.last
test = range.exclude_end? ? ->(t) { t < max } : ->(t) { t <= max }
value = block_given? ? ->(t) { yield(t) } : ->(t) { t }
while test.call(time) do
result << value.call(time)
time += step
end
result
end
This may seem like an extremely basic question but it has been eluding me for quite some time. I am trying to setup, in my controller, a way to display the time for a specific day based on that time. The time value for example I would want to display would be 10:00 AM from the value 10:00:00. I cannot seem to format the time correctly so that it can display it in that form. Here is my current code that the value will pass through:
def dayMap = new JSONArray()
daysofWeek.each{last ->
def testjsonObject = new JSONObject()
c.setTime(last.date)
int test = c.get(Calendar.DAY_OF_WEEK)
testjsonObject.put('dayofweekNumber', test)
testjsonObject.put('start_time', last.start_time)
testjsonObject.put('end_time', last.end_time)
dayMap.add(testjsonObject)
}
def weekStartTimeString = ""
def weekEndTimeString = ""
List finalList = []
dayMap.each{numberDay ->
if(numberDay.dayofweekNumber == Calendar.MONDAY){
if(numberDay.start_time.equals("09:00:00")){
weekStartTimeString += "<option value='09:00:00' selected>9:00 AM</option>"
println(numberDay)
}
else{
weekStartTimeString += "<option value='numberDay.start_time' selected>"
}
}
}
I would like to take the value numberDay.start_time and display it in that format. 10:00:00 to 10:00 AM. What is the best way of doing this as I am currently out of ideas.
Parse the time into a date object, then convert it back to a string in the format you want. For example:
def start_date = '10:00:00'
assert Date.parse('HH:mm:ss', start_date).format('hh:mm aa') == '10:00 AM'
start_date = '23:59:59'
assert Date.parse('HH:mm:ss', start_date).format('hh:mm aa') == '11:59 PM'
The date format strings are the same ones used by the Java SimpleDateFormat class.
good morning friends... I am working on with Lua scripting language for a mobile app and have a requirement as follows -
The application's main aim is to schedule appointments for an individual with a Doctor.
So once a user's appointment is scheduled, for e.g. 8th May # 4:30 PM, the user should receive a "reminder alert" before an hour i.e. # 3:30 PM.
am absolutely having a blank mind on how to get this done.
I can get the user's date-time value and use the logic that a function should invoke just before 60 mins of that date-time. And that function contains my "Alert message".
But how to do this?
Can anyone guide me with a clue?
Please let me know if any other inputs are required...
Thanks in advance.
I would take an approach like this:
1.
Store each appointment's details as a .txt file containing JSON or Lua tabular data something like this:
{
date = "14:30 01/07/2013";
dateBooked = "09:30 23/06/2013";
venue = "31 Dentist Street";
appointmentType = "Routine Teeth Cleaning";
}
2.
You can have a timer class like so
Timer = {}
Timer_mt = { __index = Timer; __add = function(a,b) a:tickBy(b) end ; }
function Timer:new(delayTime,callBack)
local timer = {callBack=callBack}
timer.initTime = os.date() --MM/DD/YY HH:MM:SS
--delayTime = HH:MM:SS
_,_,hour,minute,second = string.find(delayTime,"(%d%d):(%d%d):(%d%d)")
timer.delay = {hour=hour,minute=minute,second=second}
--time the timer started
_,_,hour,minute,second = string.find(timer.initTime,"(%d%d):(%d%d):(%d%d)")
timer.startTime = {hour=hour,minute=minute,second=second}
--time the timer started
timer.initTime = os.date() --MM/DD/YY HH:MM:SS
print(timer.initTime)
_,_,hour,minute,second = string.find(timer.initTime,"(%d%d):(%d%d):(%d%d)")
timer.currentTime = {hour=hour,minute=minute,second=second}
return setmetatable(timer,Timer_mt)
end
function Timer:tick() --returns true if time expired
currTime = os.date() --MM/DD/YY HH:MM:SS
_,_,chour,cminute,csecond = string.find(currTime,"(%d%d):(%d%d):(%d%d)")
if chour - self.startTime.hour >= tonumber(self.delay.hour) and cminute - self.startTime.minute >= tonumber(self.delay.minute) and csecond - self.startTime.second > tonumber(self.delay.second) then
self:callBack()
self.startTime.hour,self.startTime.minute, self.startTime.second = chour,cminute,csecond
--return true
end
--return false
end
t = Timer:new("00:00:02",function () print("DONE") end)
print(t.currentTime.hour,t.currentTime.minute,t.currentTime.second)
while t:tick() or true do
io.read()
end
(I just made this up so I advice you test it but it seems to work for me).
3.
On start-up, or when a new appointment is added create a new timer, and then tick() each one at some point during the main execution, you could even have a timer which is the only one you tick() and it's callback ticks() the others... Anyway set the callback for each timer to display an alarm
Haha..
I'm using Chronic to parse the time users add in the Calendar. Where the code works and implements the right time, the end result is that, IF a user adds a time, then it has no date, and because it has no date, it will not show in results. Any ideas?
def set_dates
unless self.natural_date.blank? || Chronic.parse(self.natural_date).blank?
# check if we are dealing with a date or a date + time
if time_provided?(self.natural_date)
self.date = nil
self.time = Chronic.parse(self.natural_date)
else
self.date = Chronic.parse(self.natural_date).to_date
self.time = nil
end
end
unless self.natural_end_date.blank? || Chronic.parse(self.natural_end_date).blank?
# check if we are dealing with a date or a date + time
if time_provided?(self.natural_end_date)
self.end_date = nil
self.end_time = Chronic.parse(self.natural_end_date)
else
self.end_date = Chronic.parse(self.natural_end_date).to_date
self.end_time = nil
end
end
end
Edit:
Here is the time_provided? method:
def time_provided?(natural_date_string)
date_span = Chronic.parse(natural_date_string, :guess => false)
(date_span.last - date_span.first).to_i == 1
end
First, I'm not really sure what are you asking about, because it looks like the code intentionally does what you describe... When there's time provided, the date fields are assigned nil. And I don't think that is Chronic is to blame because that's how your code works.
Not knowing your design (why there are separate date & time fields), the types of fields etc., I would suggest starting with a little kludge like this:
if time_provided?(self.natural_date)
self.time = Chronic.parse(self.natural_date)
self.date = self.time.to_date
or:
self.end_date = Chronic.parse(self.natural_date).to_date
if time_provided?(self.natural_date)
self.time = Chronic.parse(self.natural_date)
end
Or maybe the problem is outside the code you provided: in the part that is responsible for the "because it has no date, it will not show in results" behavior? Maybe you should make the conditions more flexible?