This is my query :
$casesData = $this->getEntityManager()->getRepository('Cases\Entity\Cases')
->createQueryBuilder('cases')
->select('cases.CaseId',
'cases.CreatedDate',
'cases.LeadId',
'cases.InquiryID',
'cases.FirstName',
'cases.LastName',
'cases.CityDoc1',
'cases.StateDoc1',
'cases.SSN',
'cases.Status',
'cases.CaseManagerId',
'users.first_name'
);
cases.CreatedDate is currently have "US Canada" timezone, now I want to convert base on timezone dropdown value, and I can't found any solution to convert timezone as per above query, please help me.
Actually with query builder you can't change the time zone, you have to use loop as doctrine return datetime object than you can modify the time as you wish
foreach($data as item){
$date = $item['CreatedDate']->modify('....')
}
Related
The background
I am building a Laravel application and I have an upsert method on a Booking Controller for updating/inserting bookings.
On upsert.blade.php I want to display a <select> element with a list of days into which a booking can be moved (or inserted).
There is a 'holidays' table with only one column: 'day' (of type datetime, precision 6). Each entry on this table means the system will be on holidays for that day, so bookings cannot be made or transfered into days that appear on this table.
Now, I want the <option>s in the above mentioned <select> to be disabled when they correspond to a holiday.
What I tried:
The view (upsert.blade.php)
<select>
<option value="" disabled selected>Select</option>
#foreach($days as $day)
<option value="{{ $day['value'] }}" #disabled($day['disabled'])>
{{ $day['display'] }}
</option>
#endforeach
</select>
The controller action:
public function upsert()
{
$now = Carbon::now();
$last = Carbon::now()->addDays(30);
$holidays = DB::table('holidays');
$days = [];
// Populate $days with dates from $now until $last
while($now->lte($last))
{
array_push($days, [
'value' => $now->toDateString(),
'display' => $now->format('l j F Y'),
/*
* Mark day as disabled if holidays matching current
* day is greater than 1
* DOESN'T WORK
*/
'disabled' => $holidays->whereDate('day', $now)->count()
]);
$now->addDay();
}
return view('upsert', [
'days' => $days,
]);
}
The problem
The line labelled 'DOESN'T WORK' doesn't work as expected (I expect the query to return 1 if there is a holiday for the current day in the loop, thus marking the day as disabled). It only matches the first day of the loop if it's a holliday, but it won't match any other days.
Note: I have cast the 'day' property of the Holiday model to 'datetime' so Laravel casts the value to a Carbon object when accessing it.
Attempts to solve it
I tried replacing
$holidays = DB::table('holidays');
with
$holidays = Holiday::all();
but that throws the following exception
Method Illuminate\Database\Eloquent\Collection::whereDate does not exist.
So I tried rewriting the query to (note whereDate was replaced by where):
'disabled' => $holidays->where('day', $now->toDateString().' 00:00:00.000000')->count()
But this would never match
The solution
After around 6 hours of fiddling about with this line, reading Laravel documentation and talking to ChatGPT, I couldn't come up with an answert to why this is happening so I replaced the problematic line with
'disabled' => Holiday::whereDate('day', $now)->count()
Which does the job but I think is terrible for performance due to so many (in my opinion unecessary) round trips to the database.
The question
Could anyone shed some light on this?
Although I've found a solution, I don't think it would scale and I also didn't learn a thing from the experience, I still have no idea why the first query is only matching the first day and no other days. Or why the second one using where() doesn't match any days at all when it is comparing strings and I am using the exact format the strings are stored in on the database.
Or maybe the problem is not on the query, but on the Carbon object?
If you want to reproduce it, follow steps on this gist:
https://gist.github.com/alvarezrrj/50cd3669914f52ce8a6188771fdeafcd
DB::table('holidays') instantiates an Illuminate\Database\Query\Builder object. The where method modifies that object in place.
So if you're looping from January 1st-3rd and are adding a new where condition on each loop, that's going to fail because now you are basically querying this. Obviously the day column cannot match 3 different dates.
SELECT * FROM holidays
WHERE DATE(day) = '2022-01-01'
AND DATE(day) = '2022-01-02'
AND DATE(day) = '2022-01-03'
That's also why it only worked on the first loop for you, because at that point there is only 1 where condition.
You would need to move the instantiation inside the while loop so that it gets reset on each loop. Which is basically what you did in your solution.
Re: performance, what you were trying to do would not have saved you any DB cycles anyway. Each time you call count() you are hitting the database, regardless of whether it's a new $holidays object or not.
If you're concerned about performance, one thing you could do is fetch all of the holidays between the start & end date in a single query.
// May need to call toDateString() on $now and $last
$holidays = Holiday::whereBetween('day', [$now, $last])
->get()
->pluck('id', 'day'); // Assuming day is a DATE column not DATETIME or TIMESTAMP
// This will give you a collection with an underlying array like this:
// ['2022-07-04' => 1, '2022-12-25' => 2]
while($now->lte($last))
{
array_push($days, [
// Now you can instantly look it up in the array by the date
'disabled' => isset($holidays[$now->toDateString()]),
]);
$now->addDay();
}
This is function for search by datetime .. i want to search just by date ( yy-mm-dd ) what i need to search just with date withount datetime .
I have tried all the options, but no one makes what I need.
Thank you.
if it is Mysql then you can use DATE function
as something like this
$qb->AndWhere("DATE(m.startDate) = :start");
$qb->setParameter('start',date('Y-m-d'));
for Postgres like this
$qb->AndWhere("m.startDate::date = :start");
$qb->setParameter('start',date('Y-m-d'));
Doctrine have to be setup before https://simukti.net/blog/2012/04/05/how-to-select-year-month-day-in-doctrine2/
$emConfig = $this->getEntityManager()->getConfiguration();
$emConfig->addCustomDatetimeFunction('DATE', 'DoctrineExtensions\Query\Mysql\Date');
I have a booking table where there's a bookingtime datetime field and duration field.
The duration field is integer.
In my get query for the calendar, I am showing the duration so I am trying to :
add the duration to the booking time date.
I am using this in the end of my query:
for ($i=0;$i<count($query);$i++){
$durationdate = Carbon::parse($query[$i]->bookingtime)->addHours($query[$i]->duration);
$query[$i]->end = $durationdate;
}
return $query.
The query is returning everything fine. but the "end" is returning an object
end{ date:"..." , timezone_type:3, timezon: "UTC"}
I want to modify the end to be returned like the other data in my query response as :
end : "2018-02-01 12:00:00" for example
Use the toDateTimeString() method like this:
$query[$i]->end = $durationdate->toDateTimeString();
Or the format() method:
$query[$i]->end = $durationdate->format('Y-m-d H:i:s');
The object returns is of type DateTime, so you can use the format() function to get the expect date 2018-02-01 12:00:00
$query[$i]->end = $durationdate->format('Y-m-d H:i:s');
I've searched SO and Google and can't quite find what I need.
I'm building a simple Event Calendar with CodeIgniter 2. As per the CodeIgniter documentation, this is the basic code structure and it's working...
// $data[2] contains the data for day #2, etc.
$data[2] = 'event title 1';
$data[8] = 'event title 2<br/>event title 3';
$data[13] = 'event title';
$data[24] = 'event title';
// {content} in template is where $data is inserted for each day
$prefs = array (
// my calendar options
'template' => '
{cal_cell_content}{day}<br/>{content}{/cal_cell_content}
{cal_cell_content_today}<div class="highlight">{day}<br/>{content}</div>{/cal_cell_content_today}'
);
$this->load->library('calendar', $prefs);
$year = ($year === FALSE ? date('Y') : $year);
$month = ($month === FALSE ? date('m') : $month);
echo $this->calendar->generate($year, $month, $data);
Now comes how I've set up my database table...
Each Event has a title field and that creates the $slug. (~/events/view/title-slug)
Each Event has a date field and the data format is mm/dd/yyyy
Now, I'm thinking about how I'd query the database for a particular month/year and extract the data to insert into each $data[] variable.
It seems like I'll need to do the following:
create new columns in my database table for month, day, and year.
take my date input data, after it's validated, and save it into date column.
split apart my date input data, and save each piece into month, day, and year columns.
Then I would simply query my database for year & month, then loop through these results to construct my $data[] array for each day.
Is this the correct way I should be approaching this problem? It seems very redundant to have a date column as well as month, day, and year columns. Can it be done with only the date (mm/dd/yyyy) column? Too simple? Too complex? I'd like to avoid giving the user more than one field for entering a date, and ultimately I'll have a jQuery date-picker to help ensure the proper data format.
I know this may seem like a simple problem, but I've failed to locate simple code examples online. Most of the ones I've found are out of date (CI instead of CI2), too complex for what I'm doing, or use daily content items which have URI segments that already contain the date (~/events/view/yyyy/mm/dd).
EDIT:
This is how my Model is presently setup:
return $this->db->get_where('events', array('yyyy' => $year, 'mm' => $month))->result_array();
You can leave everything as-is and just structure your query to return the month and year as separate columns:
in SQL:
SELECT id,
title,
description,
MONTH(date_field) as event_month,
YEAR(date_field) as event_year
FROM my_table
... etc ...
and in Active Record (taken from here):
$this->db->select('id');
$this->db->select('title');
$this->db->select('description');
$this->db->select("MONTH(date_field) AS event_month");
$this->db->select("YEAR(date_field) AS event_year");
$query = $this->db->get('my_table');
$results = $query->result();
Firstly, I changed my date column into the MySQL "date" format, yyyy-mm-dd, in order to take advantage of the built-in MySQL date functions.
My original $query is as follows, where the 'yyyy' and 'mm' are my redundant "year" and "month" columns:
$this->db->get_where('events', array('yyyy' => $year, 'mm' => $month))->result_array();
I simply changed it into the following using the built-in MySQL date functions:
$this->db->get_where('events', array('YEAR(date)' => $year, 'MONTH(date)' => $month))->result_array();
This solved the question. Now I no longer need to maintain the extra columns for "year" and "month".
Additionally, I can assign the "day" portion of the date column to a virtual column called dd by using the MySQL "alias" function:
$this->db->select('DAY(date) AS dd');
However, this would fail since it over-rides CI's default select('*'). So you'll have to select() all the relevant columns first or it will give an error:
$this->db->select('*');
$this->db->select('DAY(date) AS dd');
And putting it all together in the Model:
// select all relevant columns
$this->db->select('*');
/* use MySQL date functions to creates virtual column called 'dd' containing
"day" portion of the real 'date' column. */
$this->db->select('DAY(date) AS dd');
/* use MySQL date functions to match $year and $month to "year" and "month"
portions of real 'date' column. */
return $this->db->get_where('events', array('YEAR(date)' => $year, 'MONTH(date)' => $month))->result_array();
I have a mongodb that will be storing visitor data. I need to delete the data after ten minutes of not being active and will run a command through a cron. How would I do this?
Currently the collection is setup like so:
{ "_id" : ObjectId("4fd33e0b0feeda3b2406f6be"), "name" : "Dugley Reanimator", "updated" : "Some form of timestmap" }
How should I go about storing a timestamp that I search the collection with I.E for my MySql version:
$sql = mysql_query('DELETE FROM `visitors` WHERE NOW() > DATE_ADD(`last_seen`, INTERVAL 10 MINUTE)');
The ObjectId has a timestamp component to it. see the docs here. This essentially gives you a free insert time that you can use for sorting and querying.
The mongodb drives should give you a way to created an ObjectId off of a timestamp.
In Python:
gen_time = datetime.datetime(2010, 1, 1)
dummy_id = ObjectId.from_datetime(gen_time)
In Java:
Date d = new Date(some timestamp in ms);
ObjectId id = new ObjectId(d)
So once you've created an ObjectId based on "10 minutes ago" you can do a delete query using $lt
in the js console it would be:
db.collectionName.remove({_id: {$lt: <Your Object Id that represents 10 minutes ago>})
The best way to do it (if the timestamp is the same when you insert) its by using the _id field.
The _id field can indicate you the time, and you can do a $lte query to delete old values.
I've written about it here: http://blog.dicarsio.com/post/10739857186/quick-snippet-get-creation-time-from-id-on-mongodb
Your driver will use a MongoDate time (this may map to a more native representation in PHP).
You can then query using something like the following mongo statement:
db.myCollection.find({updated : { $lte : new ISODate("2012-06-09T16:22:50Z") } })
A rough translation for PHP would be:
$search = array(
'updated' => array(
'$lte' => new MongoDate($tenMinutesAgo))
);
$collection->find($search)
Or (Caveat: not tested):
$tenMinutesAgo = new DateTime();
$tenMinutesAgo->modify('-10 minutes');
$search = array('updated' => array('$lte' => $tenMinutesAgo));
$collection->find($search)