I have a query to get the number of insertions grouped by months. I have beberlei Doctrine extensions already installed and working, but the array return have the month number as key. How will be used in a chart line, I want to show the month name instead of month number.
What is the best way to do this?
This the query:
//get and format the current year
$date = new \DateTime();
$year = $date->format('Y');
//create query
$qb = $this->_em->createQueryBuilder();
$qb->select(['MONTH(p.createdAt) as month', 'count(ccp) as insertions'])
->from(CareConnectPatient::class, 'ccp')
->join('ccp.person', 'p')
->where('YEAR(p.createdAt) = :year')->setParameter('year', $year);
$qb->groupBy('month');
return $qb->getQuery()->getScalarResult();
And I do that with that result:
`$countMonths = count($cCPatientGroupedByMonth);
for ($count = 0; $count<$countMonths; $count++){
$arrayKeyAsMonth[$cCPatientGroupedByMonth[$count]['month']] = $cCPatientGroupedByMonth[$count]['insertions'];
}`
What gives me something like this:
array:3 [
4 => "1",
8 => "2",
9 => "2"
]
I what to know the best way to make this appear as:
array:3 [
april => "1",
august => "2",
september => "2"
]
Sorry for bad english and thanks!
have you tried using MONTHNAME() function?
instead of:
$qb->select(['MONTH(p.createdAt) as month', 'count(ccp) as insertions'])
try:
$qb->select(['MONTHNAME(p.createdAt) as month', 'count(ccp) as insertions'])
Related
This question already has answers here:
Convert one date format into another in PHP
(17 answers)
Closed 9 months ago.
I would like to get next day.
$nextSunday = date($saturdayList[$k], strtotime("+1 day"));
saturdayList array is
Array
(
[
0
] => 2022-11-05
[
1
] => 2022-11-12
[
2
] => 2022-11-19
[
3
] => 2022-11-26
)
When $k is 0
nextSunday return
2022-11-05
Please refer to the manual page for the date function here: https://www.php.net/manual/en/function.date.php.
You can see that the first param should be the format of the returned date, e.g. 'Y-m-d', not the date you want to add 1 day to.
The code should be something like
$nextSunday = date('Y-m-d', strtotime($saturdayList[$k] . " +1 day"));
The second parameter of strtotime takes a base timestamp. So pass in the timestamp of the date as the second parameter.
$nextSunday = date("Y-m-d", strtotime("+1 day", strtotime($saturdayList[$k])));
I'm trying to pass a test that involves running a query that returns a series of logins to test whether two arrays are equal in the test.
In the past I have tried changing the format of the query to make the test pass as well as editing the arrays and eventually it equalled the two arrays. Unfortunately the test still doesn't pass.
The function that performs the query to get a series of dates of logins:
public function getLogins(): array
{
return $this->createQuery()
->select('date AS datetime, COUNT(id) as total')
->orderBy('datetime', 'DESC')->groupBy('datetime')
->where('date >= -24 hours')
->getQuery()
->getResult();
}
This is the method in the test class:
public function testGetLogins()
{
$dateLogins = $this->repository->getLogins();
$this->assertCount(4, $dateLogins, "Four instances");
$this->assertEquals([
["datetime" => new \DateTime("now -3 minutes"), "total" => "1"],
["datetime" => new \DateTime("now -7 days"), "total" => "1"],
["datetime" => new \DateTime("now -1 year"), "total" => "1"],
["datetime" => new \DateTime("now -600 days"), "total" => "1"]
], $logins, "The login instances returned match the expected times");
}
I'm expecting the test to pass but instead it is displaying this:
Test Output
The expected and actual arrays are both equal so I'm unsure as to what is causing the test to fail.
\DateTime format contains information about seconds as well. new \DateTime("now -3 minutes") will return now minus 3 minutes but exact amount of seconds, which will be always different, depending on the time when you did launch the test. Apparently you want to compare dates till minutes, so you have to format your dates before comparsion, therefore you have to compare each set separately:
$expectedValues = [
["datetime" => new \DateTime("now -3 minutes"), "total" => "1"],
["datetime" => new \DateTime("now -7 days"), "total" => "1"],
["datetime" => new \DateTime("now -1 year"), "total" => "1"],
["datetime" => new \DateTime("now -600 days"), "total" => "1"]
];
for ($i = 0; $i < count($expectedValues); ++$i) {
$actualDate = (new \DateTime($logins[$i]['datetime']))->format('Y-m-d H:i');
$expectedDate = ($expectedValues[$i]['datetime'])->format('Y-m-d H:i');
$this->assertEquals($expectedDate, $actualDate);
$this->assertEquals($expectedValues[$i]['total'], $logins[$i]['total']);
}
I have a table with sales. From this table i take all results of the last 30 days, sum the prices with the same date and get this as array.
SQL:
SELECT date
, price
, id
, SUM(price) AS daylieprice
FROM sales
WHERE id = :id
AND date BETWEEN DATE_FORMAT(CURDATE() , '%Y-%m-%d') - interval 1 month AND DATE_FORMAT(CURDATE() , '%Y-%m-%d'))
GROUP
BY date
So i have for example:
ARRAY ['date'] - ARRAY ['daylieprice']
"2017-03-29" - "1"
"2017-04-02" - "5"
"2017-04-04" - "3"
Google chart is looking like that:
['<? echo date('d', strtotime("-2 day")) ?>', VALUE]
['<? echo date('d', strtotime("-1 day")) ?>', VALUE]
['<? echo date('d') ?> ', VALUE]
Is there a way to output the value of the array like that:
date('d', strtotime("-2 day") , ARRAY ['daylieprice']);
date('d', strtotime("-1 day") , ARRAY ['daylieprice']);
date('d', ARRAY ['daylieprice']);
Should mean to take the array value easy with date('d') or date('d', strtotime("-1 day") witouth making a loop for each value ?
Or does i have to make for every day a sql request?
I came up with this. I use DateTime to give more control and felxibility with input and output formats. This loops through your input array and subtracts 2 days from first entry, 1 day from 2nd entry and keeps 3rd entry the same:
<?php
$input = [
[
'date' => '2017-03-29',
'daylieprice' => 1,
],
[
'date' => '2017-04-02',
'daylieprice' => 5,
],
[
'date' => '2017-04-04',
'daylieprice' => 3,
],
];
$output = [];
$number_of_dates = count($input) - 1;
foreach ($input as $v) {
$date = DateTime::createFromFormat('Y-m-d', $v['date'])
->modify(sprintf('-%d days', $number_of_dates))
->format('Y-m-d');
$number_of_dates--;
$output[] = "'" . $date . "', " . $v['daylieprice'];
}
This produces an array like:
Array
(
[0] => '2017-03-27', 1
[1] => '2017-04-01', 5
[2] => '2017-04-04', 3
)
Hope this helps and you can figure out exactly how to implement it to solve your problem.
Edit: just saw echo date('d' so maybe you only want the day of the month, that's easy, you can just change ->format('Y-m-d'); in the loop to ->format('d');
Demo: https://eval.in/784353
I am given an array containing periods for a year as following.
$year = '2016';
$periods = [
[
'name' => "Name One",
'startDate' => '01/01/2016',
'endDate' => '03/31/2016'
],
[
'name' => "Name Two",
'startDate' => '04/01/2016',
'endDate' => '12/31/2016'
]
];
The number of periods may vary, hence, the array periods may have any number of elements (say 5 elements, meaning 5 periods for the given year). Now I need to make sure that the periods do really make up a year, that is, two periods cannot overlap and the periods collectively do sum up to be the specified year.
I've tried many different ways, but failed to come up with any efficient solution at all.
I am using Laravel 5, hence Carbon package. But I'll be glad to get this done even in Basic PHP. So all suggestions are welcome
Give this a try - there may be a more elegant solution but I think this works. I've used Carbon, as it's a got some very useful helper methods.
I've assumed your $periods array will be in date order. If it's not, you could just usort it.
$year = '2016';
$periods = [
[
'name' => "Name One",
'startDate' => '01/01/2016',
'endDate' => '03/31/2016'
],
[
'name' => "Name Two",
'startDate' => '04/01/2016',
'endDate' => '12/31/2016'
]
];
// set a start position
$currentPosition = Carbon::create($year, 1, 1)->startOfDay();
// and the end of the year
$endOfYear = Carbon::create($year, 1, 1)->addYear()->startOfDay();
// iterate periods
foreach ($periods as $period) {
$start = Carbon::createFromFormat('m/d/Y', $period['startDate'])->startOfDay();
$end = Carbon::createFromFormat('m/d/Y', $period['endDate'])->endOfDay();
// start of this period should follow the last (??)
if ($start < $currentPosition) {
throw new Exception("$start is earlier than $currentPosition");
}
// must follow on from the current position
if ($currentPosition->diffInDays($start) > 0) {
throw new Exception("$start doesn't follow $currentPosition");
}
// check it doesn't go over the end of the year
if ($currentPosition->addDays($start->diffInDays($end)) > $endOfYear) {
throw new Exception("$end takes us over the end of the year!");
}
$currentPosition = clone $end;
}
// did we reach the end?
if ($currentPosition->addDay()->startOfDay() != $endOfYear) {
throw new Exception("Full year not accounted for");
}
// we're done
echo 'Full year accounted for'.PHP_EOL;
I'm using this code to retrieve news items from my MongoDB:
foreach (collection("news")->find(["created"=>$time]) as $news)
Now I would like to find only those news articles with "created" unix timestamp that matches specific month of the specific year, like April 2014.
Any help would be appreciated.
Cheers.
EDIT: Thank you all for your effort, and yes, it's unix timestamp.
How did you create the Unix Timestamp? How is it represented in the document?
Are you using the MongoDate type, or are you using an integer?
If you are using the MongoDate type then you need to construct MongoDate objects and use them for your $gte and $lt conditions
$article = array(
"title" => "My first article",
"content" => "This is good news",
"published" => new MongoDate(),
"author" => "Random guy on the internet",
);
$collection->insert($article);
$start = new MongoDate(strtotime("yesterday"));
$end = new MongoDate(strtotime("tomorrow"));
$cursor = $collection->find(array("ts" => array('$gt' => $start, '$lte' => $end)));
foreach($cursor as $article) {
var_dump($article);
}
See http://www.php.net/manual/en/class.mongodate.php for more info
you'll have build your own query:
SELECT * FROM news WHERE created >= $start_date AND created <= $end_date
where:
assuming created is unix timestamp, otherwise you should skip strtotime function
// first day of april 2014
$start_date = strtotime(date('2014-04-01'));
// last day of april 2014
$end_date = strtotime(date('2014-04-t'));
You could use DateTime::createFromFormat to create your timestamps.
$begin = DateTime::createFromFormat('!Y-m', '2014-04');
$end = clone $begin;
$end->modify('next month');
echo $begin->format('Y-m-d H:i:s'). PHP_EOL; // 2014-04-01 00:00:00
echo $end->format('Y-m-d H:i:s'); // 2014-05-01 00:00:00
And build more complex condition.
collection("news")
->find(["created" => array(
'$gte' => $begin->getTimestamp(),
'$lt' => $end->getTimestamp())]);