Rails ActiveRecord Find / Search by Date - activerecord

I am trying to find records by 'created_at' date - the database column type is 'datetime' and
I am using the UI DatePicker from jQuery
my url look like this: "localhost:3000/users_supported?selected_date=2012-10-31"
So far i am doing good :) and my query in controller looks like this:
#support_histories = current_agent.support_histories.where(:created_at => Date.parse(params[:selected_date]))
How to properly extract records by 'date' only from the 'datetime' db column
I tried doing this in Rails Console, but no luck there:
sh = SupportHistory.where(:created_at => DateTime.parse('2012-10-31'))
sh = SupportHistory.where(:created_at => Date.parse('2012-10-31'))
sh = SupportHistory.where(:created_at => DateTime.strptime('2012-10-31', '%Y-%m-%d'))
I got records if i do like mentioned below, but that's not useful to me as i am trying to find record by 'date' not by 'DateTime'
sh = SupportHistory.where(:created_at => '2012-10-31 19:49:57')

selected_date = Date.parse(params[:selected_date])
# This will look for records on the given date between 00:00:00 and 23:59:59
sh = SupportHistory.where(
:created_at => selected_date.beginning_of_day..selected_date.end_of_day)
Time Zones may be a concern you need to look into, but this should work if all your times are in the same time zone.

A simple solution I use sometimes is to cast the date(time) field as text on the database rather than parse the string into date on application side. For your case that would be:
where('CAST(created_at AS text) LIKE ?', params[:selected_date])
Might not be the most effective on the database (depending on the context you use it in) but saves a lot of pita on the application side.

I solved this problem by creating a method in model like below,
Say, my model is ticket.rb
def created_date
self.created_at.to_date
end
then I queried like this,
selected_date = Date.parse(params[:date])
Ticket.all.map{|t| t if t.created_date == selected_date}.compact
This gives me accurate results that matches with the chosen date by the user.

Your current query doesn't work because you are querying a date on a datetime column. Those are two different data types.
For a datetime column, you'll need a datetime filter. You can do this by passing a DateTime object to the where clause. However, in your case you want records for the entire day so you'll specify a range between 00:00:00 and 23:59:59.
Before Rails 5.1:
SupportHistory.where(created_at: date.beginning_of_day..date.end_of_day)
Rails 5.1 and onwards: (this will generate the exact same range using #all_day)
SupportHistory.where(created_at: date.all_day)

If you want to parse a specific datetime
SupportHistory.where("created_at>=?", DateTime.parse('10 Dec 2021 11:54:00 PST -08:00'))

Related

Correct time-zone for carbon on many records

So i'm trying to set correct time-zone on Carbon::today() for getting all of the results created for this day.
Let's explain a little bit more.
I have a command that archive the Notes when created_at column is today, so I get all Notes that are created today and check them in foreach based on Building model timezone
Database structure:
Buildings:
-id
-name
-timezone
Notes:
-id
-name
-created_at
-updated_at
-building_id (reference id on buildings)
My code:
$notes = Note::where('archived', null)
->whereDate('created_at',Carbon::today())
->get();
foreach($notes as $note) {
// Set the current timezone
date_default_timezone_set($note->building->timezone)
$note->update([
'archived' =>1,
'archived_at'=>Carbon::now()
]) // update archive status etc...
}
I want Carbon::today() to be with the current timezone of the record building.
I've tried with query something like that but still the issue is not solved:
select
*
from
`notes`
inner join `buildings` on `notes`.`building_id` = `buildings`.`id`
where
date(`notes`.`created_at`) = CONVERT_TZ('NOW()', 'UTC', `building`.`timezone`);
Is there any way to do that? Thanks. :)
date_default_timezone_set is as the name says for the default, you should not change the default timezone multiple times during the same process.
Actually it should just always stay UTC so you easily scale and share it outside, then you can simply get now or today for a given timezone:
Carbon::today($note->building->timezone)
Carbon::now($note->building->timezone)
But a better solution is to have also your dates stored as UTC in your DB, so you convert created_at from timezone to UTC instead of converting NOW from UTC to building.timezone, it would a better approach for data consistency in your DB.

Count maching date data [duplicate]

I need to call ToShortDateString in a linq query suing lambda expressions:
toRet.Notification = Repositories
.portalDb.portal_notifications.OrderByDescending(p => p.id)
.FirstOrDefault(p => p.date.ToShortDateString() == shortDateString);
but I get the error:
An exception of type 'System.NotSupportedException' occurred in
System.Data.Entity.dll but was not handled in user code
Additional information: LINQ to Entities does not recognize the method
'System.String ToShortDateString()' method, and this method cannot be
translated into a store expression.
What can I do, considering that I do need to use ToShortDateString() ?
Thanks.
Linq to Entities cannot convert ToSortDateString method into SQL code. You can't call it on server side. Either move filtering to client side (that will transfer all data from server to client), or consider to use server-side functions to take date part of date (you should pass DateTime object instead of shortDateString):
EntityFunctions.TruncateTime(p.date) == dateWithoutTime
You shouldn't be forcing a string comparison when what you're working with is Date/time data - as soon as you force string comparisons, you're suddenly having to deal with how the strings are formatted.
Instead, have something like:
var endDate = targetDate.AddDays(1);
toRet.Notification = Repositories
.portalDb.portal_notifications.OrderByDescending(p => p.id)
.FirstOrDefault(p => p.date >= targetDate && p.date < endDate);
(Assuming that targetDate is whatever DateTime variable you had that was used to produce shortDateString in your code, and is already a DateTime with no time value)
Try this,
You can also used with below code.
Activity = String.Format("{0} {1}", String.Format("{0:dd-MMM-yyyy}", s.SLIDESHEETDATE), String.Format("{0:HH:mm}", s.ENDDATETIME))
ToShortDateString() method usually used to work only with date and ignore time stamps.
You will get exactly today result-set by using the following query.
Repositories.portalDb.portal_notifications.OrderByDescending(p => p.id)
.FirstOrDefault(p => p.date.Date == DateTime.Now.Date);
By using Date property of DateTime struct you can just fetch record of that date only.
Note: Linq to Objects. Only works if you CAN (or have option) to bypass ToShortDateString() method

date function error in rails 3

I am trying to add a date conditional to my controller index action:
#events = Event.where("date" => Date.today.to_s).order("date").page(params[:page]).per_page(5)
I am trying to make my view only show events that have a date value greater than or equal to today's date. For example if an event has a date value of 2013-05-13 it should not be shown because that event has already happened and only events with a date value of today's date or later should be shown.
The problem is, the index view isn't returning any events and I have created an with a date value of 2013-05-30 which means it should work. Any ideas?
Thanks in advance
This is actually going to return everything where the date equals today:
Event.where("date" => Date.today.to_s)
What you probably want instead is:
Event.where("date >= ?", Date.today)
ActiveRecord will interpolate the date into the ?. Also, you don't need to call to_s on it, ActiveRecord will the date for you.
Try this:
In your model use a scope like so:
scope :recent_event, lambda { where('date >= ?', Date.today ) }
Then in your controller write
#events = Event.recent_event.order("date").page(params[:page]).per_page(5)

Extract only date part in a datetimein LINQ

We have some data in a DataTable and we are using the query like this to get what we need.
IEnumerable<Results> subResult = from query in datatable.AsEnumerable()
select new Results
{
Name = query.Field<string>("Name"),
Date = query.Field<DateTime?>("Date")
}
This above query returns what i need but date in full format (Ex: m/dd/yyyy hh:min:sec am/pm) but we need only date part of it(only mm/dd/yyyy need to be pulled in). When looked in the properties of this, couldn't find an implicit way to get it, please help me in getting this result. Thanks.
The DateTime class has all the properties you just mentioned. You should try to fix your display with the ToString("anyformatyouwant") formats.
What about this?
Date = query.Field<DateTime?>("Date").Date
This will give you just the date part:
IEnumerable<Results> sub-result= from query in datatable.AsEnumerable()
where new Results
{
Name = query.Field<string>("Name"),
Date = query.Field<DateTime?>("Date").Date
}
However if you just want to display the date somewhere (meaning you're not using this to do date grouping, etc. then I would just specify the display format in your UI layer.
AFAIK there is no Date Class in .net, if you want pure date you should write a Class for that, otherwise you can pull out the part as a string
DateTime.Now.Date.ToString("yyyy/MM/dd")
gives you the current date in string type, but if you get the .Date part it gives you a DateTime object which still has a time part showing AM 12:00:00:0 blah blah

MongoMapper: finding all documents created on a specified date

I need to write a query that finds all documents created on a specified date.
Let's suppose that the date is today.
I tried this:
Document.all(:created_at => Date.parse(Time.now.strftime('%Y/%m/%d')))
but I got:
Cannot serialize an object of class Date into BSON.
Thanks for your help.
UPDATE
This link explains how to do so Date Range Queries With MongoMapper.
Document.count( :created_at => { '$gt' => 2.days.ago.midnight, '$lt' => 1.day.ago.midnight } )
UPDATE: This link explains how to do so Date Range Queries With MongoMapper.
Document.count( :created_at => { '$gt' => 2.days.ago.midnight, '$lt' => 1.day.ago.midnight } )
Your :created_at is a Date (as in "JavaScript-style Date with both date and time-of-day components"), right? You'll need to figure out the boundaries of the date in question in UTC, build Time instances for those boundaries, and then search for everything between those times.
Assuming that your local time zone is correctly configured and you want everything that was created on 2011-11-21, then something like this should get you there:
start_time = Time.new(2011,11,21, 0,0,0).utc
end_time = Time.new(2011,11,22, 0,0,0).utc
docs = Document.where(:created_at => { :$gte => start_time }).
where(:created_at => { :$lt => end_time })
You could also use Time.new(2011, 11, 21).utc and Time.new(2011, 11, 22).utc but I like the extra zeros as a reminder that I'm not really working with just a date.
Just use Time.now instead. The ruby driver knows how to deal with Time objects.
doc = {:created_at => Time.now}
or
doc = {:created_at => Time.utc(12,1,12)} # year, month, day
Then, you can test if the document will serialize without throwing an error in irb like this:
require 'bson'
BSON.serialize(doc)
If you get an error, try again. If it spits out a serialized bson object, you are good to go!
If you are curious, check out the source of the to_mongo method in the mongomapper driver here
Use the technique #mu-is-to-short pointed out to create the date.
But the format of the where statement can be simpler:
date = Time.new(2021,1,24, 0,0,0).utc
docs = Document.where(:updated_at.gte => date).all

Resources