I have column which stores only time. I want to convert to it into datetime and then to a specific timezone. When I do it on console using only the attribute, it shows correct conversion value. But when I use it in query the query shows the current time in UTC. Suppose I have time "05:15" stored in Central time. Now when I want to fetch records for a interval of 30 minutes plus and minus of this time, I do following,
day = Time.now
# departure_time_from _db below is the name of column in table which store time
departure = departure_time_from _db.change(:day => date.day, :month => date.month, :year => date.year)
departure = departure.in_time_zone("Central Time (US & Canada)")
When I execute above code on console and see the value, it shows correct converted value. But when I use this variable in below query, current time gets used instead of the departure time.
Model.where("column_name > ? and "column_name < ?, departure - 30.minutes, departure + 30.minutes)
The time used in above query should be the time I want i.e Central time zone, but in query output, it shows UTC being used.
Please let me know what i am missing.
It shouldn't matter what time zone the query uses in the where clause as long as it's the same time representation. The time you're seeing in your query output from Rails is most likely the UTC equivalent of the ruby DateTime object being passed to the where statement. So if departure is 12:00 noon (UTC -6) in your Ruby code then the time shown in the SQL query will be 18:00, which corresponds to noon CST.
Related
In the project I'm working on I have a daily command that basically checks the date of the last record in the database and tries to fetch data from an API from the day after and then each month after that (the data is published monthly).
Basically, the last record's date is 2019-08-30. I'm mocking as if I were running the task on 2019-09-01 with
$test = Carbon::create(2019,9,1,4);
Carbon::setTestNow($test);
I then create a monthly period between the next day of the last record's date and the last day of the current month like so:
$period = CarbonPeriod::create($last_record_date->addDay(), '1 month', $last_day_of_current_month);
Successfully generating a period with start_date = 2019-08-31 and end_date = 2019-09-30. Which I use in a simple foreach.
What I expected to happen is that it runs twice, once for August and once for September, but it's running only once for the start date. It's probably adding a month and going past the end date, but I don't know how to force the behaviour I'm looking for.
TL;DR:
$period = CarbonPeriod::create('2019-08-31', '1 month', '2019-09-30');
foreach ($period as $dt) {
echo $dt->format("Y-m") . "<br>\n";
}
This will print just 2019-08, while I expect 2019-08 and 2019-09. What's the best way to achieve that?
Solution :-
You can store actual date in $actual_day and current date for occurring monthly in $current_day. Put a check on comparing both dates, if not matched then make it on the same day it will skip 30,31 case in case of February month.
$current_date = $current_date->addMonths(1);
if($current_date->day != $actual_day){
$date = Carbon::parse($date->year."-".$date->month."-".$actual_day);
}
Your start date is 2019-08-31. Adding a month takes you to 2019-09-31. 2019-09-31 doesn't exist so instead you get 2019-10-01, which is after your end date. To avoid this I'd suggest you use a more regular interval such as 30 days.
Otherwise you're going to have to rigorously define what you mean by "a month later". If the start date is 31st Jan is the next date 28th February? Is the month after 28th or 31st March? How do leap years affect things?
I'm trying to add 2 DateTime fields which are stored as strings in Azure. The first datetime is supposed to get the current date and time now and this stores the date time as 12/02/2019 09:01 correctly, but currently the second field is supposed to get the current date and time and add 30 minutes but it is storing is like only the date eg 12/02/2019. This is my current code:
symptomFeedback.DateTime = DateTime.Now.ToString("dd/MM/yyyy HH:mm");
symptomFeedback.Datetimelimit = DateTime.Now.AddMinutes(30).ToString("dd/MM/yyyy HH:mm");
I am using the following ruby code, with the PG gem, to return a timestamp that is in Postgres "timestamp without timezone" format. Instead of returning the current value, I would like it to return the value (-1 hour).
def get_latest_timestamp(id)
conn1 = PGconn.open(:dbname => 'testdb')
res = conn1.exec("SELECT MAX(time_of_search) FROM listings WHERE id=#{id}")
res.values[0][0]
end
In Postgres, you can add or subtract an interval to or from a timestamp to produce another timestamp, as described here.
So in this case, assuming time_of_search is a timestamp, you could do
"SELECT MAX(time_of_search) - INTERVAL '1 hour' FROM listings WHERE id=#{id}"
I run the following in Rails:
coe = trackers.where(:trackable_type => "Mailing").count(:group => 'DATE(created_at)')
which returns a hash with the items nicely grouped.
However I want to group not by date only by date but by the hour, but not the minutes or seconds.
How can I run this query so all the heavy lifting is done by Postgresql and not convert after I get the data set back?
My mistake I want to group by Date and Hour. Sorry for the confusion.
It sounds like you want the date_trunc() function:
http://www.postgresql.org/docs/current/interactive/functions-datetime.html#FUNCTIONS-DATETIME-TABLE
I want to group not by date but by the hour, but not the minutes or
seconds.
Bold emphasis mine.
So date_trunc()is probably not what you want, but EXTRACT or date_part():
coe = trackers.where(:trackable_type => "Mailing").count(:group => 'EXTRACT (hour FROM created_at)')
I have an object which contains a list of due dates, I am trying to build a system which returns the due date when a specified date is 1 month or less before the due date. It should return the due date in this format "1st Feb 2009". Let me clarify, using my current code
#Build array of estate objects
estate.due_dates = "1st Feb, 3rd May, 1st Aug, 5th Nov"
estate2.due_dates = "28th Feb, 31st May, 31st Aug, 30th Nov"
estates = [estate,estate2]
set_due_date_on_estates("1st Jan 2009",estates) #Run function - should return "1st Feb 2009,28th Feb 2009"
def set_due_date_on_estates(date,estates)
estates.each{|estate|
estate.due_dates.split(",").each{|due_date|
((date)..(date >> 1)).each{|current_date|
estate.set_reminder(due_date + current_date.strftime("%Y")) if current_date.strftime('%d %m') ==
Date.parse(due_date).strftime('%d %m')
}
}
end
}
The issue I am having, is that my list of due dates doesnt have a Year, so I am looping through my range and checking if the dates are equal using the format "%d %m". If so I am setting the reminder in the estate object by using the current "due date" in the loop concatenated with the Year of the "current date" in the loop.
Am not too happy with the code, in particular the nested loops and wondered if there was a better way I could deal with checking that the due_dates where in the date range, even though the due_dates dont have a year. Thanks
You could use date parsers: Kronos, chronic
Example for kronos:
def parse_date(date)
Kronos.parse(date.sub(/\d{4}$/, ''))
end
This function gives you a Kronos object without year which is more easily to compare, build range and so on.
Yes you can use Chronic and also you can write a worker which will keep checking if the specified date is 1 month or less before the due date at regular interval. And ask that worker to do something if result is true (say send you an email or anything if date is within due date) you can find more information about worker by googling Resque and Redis. Another option would be to convert both dates on some base reference and then do the calculations.