Outputting the name of the month instead of the number - php

I have a query which returns 3 fields, one of which is the month as a two digit number.
I want to basically have it so if month == 1 output january, if month == 02 output febuary etc
This is what I am trying, but this does not work at all, and prevent the entire column from being displayed in PHP.
while ($row = mysql_fetch_array($sqlstr)) {
if ($row['theMonth']=="6") {
echo "<td>{June}</td>";}
echo "<td>{$row['sumSales']}</td>";
echo "<td>{$row['sumPurchases']}</td>";
echo "</tr>";
}
}
What is the correct way to do what I want, and why is what I am doing wrong?
The SQL query I am using is:
SELECT theMonth, sum(Sales) as sumSales, sum(Purchases) as sumPurchases
FROM
( SELECT date_format(saledate, '%Y-%m') AS theMonth, sales.cost as Sales, 0 AS Purchases
FROM sales, products
WHERE sales.product=products.name AND category='Food' OR category='Bocas'
OR category='Bebidas' OR category='Flor de cana por botellas'
OR category='Vino por botella' OR category='hora feliz'
UNION ALL
SELECT date_format(purchasedate, '%Y-%m') AS theMonth, 0 as Sales, purchases.cost as Purchases
FROM purchases
) AS all_costs
group by theMonth
I donĀ“t think I could just replace
SELECT date_format(purchasedate, '%Y-%m') AS theMonth
with
SELECT MONTHNAME(purchasedate) AS theMonth
So what would be the best way to return the month name as text in SQL?

In your SQL you can use DATE_FORMAT to convert a date to a month name:
SELECT DATE_FORMAT(NOW(), '%M')
July
The list of allowable specifiers can be found in the MySQL documentation.
(MONTHNAME should also work too.)
The reason why your current method doesn't work is because you are currently outputting both the year and the month (e.g. "2010-06") and this string doesn't compare equal to the string "6".

.
function month_name($int) {
return date( 'F' , mktime(1, 1, 1, (int)$int, 1) );
}
echo month_name(2); // February

First option would be to modify your SQL query to return the month as a name rather than (or as well as) a numeric. See MONTHNAME
Second option would be to use PHP's date functions to generate the name for you
$monthName = date('F',mktime(1,1,1,$row['theMonth'],1,2010));
Third would be to use a monthnames array, similar to zebediah's suggestion

There is probably a php builtin for that, but not using anything like that
$monthNames = array(1 => "January", 2 => "Febuary", 3 => "March", .... 12 => "December");
while ($row = mysql_fetch_array($sqlstr)) {
echo "<td>{$monthNames[$row['theMonth']]}</td>";
echo "<td>{$row['sumSales']}</td>";
echo "<td>{$row['sumPurchases']}</td>";
echo "</tr>";
}

You've got a closing curly brace at the end of the line on your first echo statement. That's causing PHP to prematurely terminate the conditional block, then it has a parse error when it stumbles across your last closing curly brace since it doesn't have an opening match.
You can get the name of the month from a timestamp (if you have one) with the date function. date('F', $timestamp); see the php date function reference
Doing it in the SQL statement is probably your easiest and most performance-friendly way of handling this particular situation.

Related

show data only if currentmonth and currentyear are larger than

Let say currentmonth is 06 and currentyear 2017
i have dropdown of year and month ..
if i select year 2017 and month of July which is larger then currentmonth
how do i show there is not data available yet
my current code..and its not working..i'm a newbie and not sure im doing this right or not...
$mystartingyear=2017;
$mystartingmonth=01;
$currentmonth=date("m");
$currentyear=date("Y");
if ($currentyear >= $mystartingyear && $currentmonth >= $mystartingmonth)
{
echo "Show Data";
}
else
{
echo "No Data yet";
}
i also tried it like this
$mystartingyear=2017;
$mystartingmonth='01';
$currentmonth=12;
$currentyear=2017;
//$currentmonth=date("m");
//$currentyear=date("Y");
if ($currentyear >= $mystartingyear && $currentmonth >= $mystartingmonth)
{
echo "Show Data";
}
else
{
echo "No Data yet";
}
it always display "show data"
Edit:
Integers from 01 to 07 are ok just as long as you don't do 010 (with 3 integers) since that will be represented as 8. But as soon as you start hitting 08 and 09 for the months of August and September (which may be what's in your unknown dropdown), you will have problems.
So it's best you quote it.
Consult "Footnotes".
Original answer:
The leading zero in 01 for:
$mystartingmonth = 01;
^^
is treated as an octal.
It needs to be quoted:
$mystartingmonth = '01';
Octals references:
http://php.net/manual/en/language.types.integer.php
https://en.wikipedia.org/wiki/Octal
Footnotes:
If your current code is failing you, then something else is failing you.
You mention in your question that you're using this from a dropdown and that code wasn't included, nor how it's being passed.
Use PHP's error reporting, set to catch and display:
http://php.net/manual/en/function.error-reporting.php
Verify your conditional statement's logic also; both conditions must be met.
There is missing semicolon after first echo i.e. code should be
echo "Show Data";
Then every thing should work fine,
The date(); function in php returns the date in string and when you compare a string with integer it is implicitly converted into equivalent integer variable,if you want for sure you can use intvar(); function which converts variable to equivalent integer.But in your case it is not necessary.For more about i recommend you to read php manual .

PHP - Select data from where timestamp is

I have a piece of code which will select x number of days into the future and print it out.
I'm then trying to select data from those timestamps, and print out accordingly:
Below I am selecting the number of days in the future it should loop ($max) and how many rows/data there is ($data["cnt"])
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from xeon_users_rented WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
$data=$stmt->fetchAll();
$max = max(array_map(function($d){
return $d['days'];
}, $data));
$expireData = array();
I then loop through x number of days in the future and print it out: (Let's say that $x is = 10)
for($x = 0; $x <= $max; $x++){
if ($data[$x]["cnt"] > 0){
$expireData[] = $data[$x]["cnt"];
}else{
$expireData[] = 0;
}
$stamp = strtotime('+'.$x.' day', time());
$expireDays[] = date("Y/m/d", $stamp);
}
I then print out the days data and the data:
<?php echo implode("', '", $expireDays); ?>
<?php echo implode("', '", $expireData); ?>
Which gives me:
'2014/11/05', '2014/11/06', '2014/11/07', '2014/11/08', '2014/11/09', '2014/11/10', '2014/11/11', '2014/11/12', '2014/11/13', '2014/11/14', '2014/11/15'
and (where each digit represent a value for that specific date)
2,8,0,0,0,0,0,0,0,0
So far so good. The only problem here is, that the data (2,8,0,0etc.) is not correct. It should for example be:
0,0,2,0,0,0,8,0,0,0
My question is: How can I print out the data, where it matches the timestamp (xeon_users_rented.expire)?
To simplify my answer from before and to answer your question directly "How can I print out the data, where it matches the timestamp"?
You need to first put the unix timestamp of "strtotime('+'.$x.' day', time());" into an array from your original loop. Remove the expiredays[] stuff from that loop.
Then loop through that array and then use array_search for finding any matching indexes in the $data array.
if (found in $data array)
$expireDays[] = $data[array_search position]['cnt'];
else
$expireDays[] = 0;
From what I have gathered in what you are trying to establish, the sql query (for example) returns an array such as:
$data = array(
array("days"=>232975857, "cnt"=> 4),
array("days"=>232975867, "cnt"=> 10),
array("days"=>232976689, "cnt"=> 0),
array("days"=>232976688, "cnt"=> 2)
);
The max in your case is 10. However, please note that your code (below):
$max = max(array_map(function($d){
return $d['days'];
}, $data));
could return a lot of PHP E_NOTICE errors and be slow because you are working out a maximum from the unix_timestamp at that stage which is for example 232975867 (far too many loops I suspect that you need). The max should be worked out in the following way I suspect:
$max = count($data);
In my case (from my data example example) this will return something like 4 for which your for loop code will need to reference "<" not "<=". To optimise this I would actually put straight into the for loop "...; $x < count($data); ...;" unless of course you need the $max later.
Here is a big issue for me. I don't see where currently you have any correlation between the $stamp variable and the "days" column from your sql statement. Perhaps I have not seen enough information from you to fully understand or I am interpreting your question incorrectly but your sql for one will not necessarily return the same dates as the stamp variable will calculate and will not certainly return a cnt of 0 for any dates that do not exist in that table. This is why:
if ($data[$x]["cnt"] > 0){
part of the section is unnecessary and possibly incorrect.
To answer your question why do you get "2,8,0,0,0,0...." instead of the order you expected is because the sql does not return 0 cnt values as quite simply the date does not exist in it's table and your implode still returns '0's appended as you forcibly added the 0's afterwords with the line:
$expireData[] = 0;
First of all, you need to fill your data (or re-write your data to contain cnt of '0's in the correct array places). You can achieve this from the sql level with a subquery that ensures missing dates are contained and then a cnt value of 0 is enforced. I'll leave this to you to work out however another way (via PHP) is to do the following (pseudo code):
place each 'stamps' (in unix format) in array from previous loop
forloop $i through $stamps
array_search $stamps against $data['days']
if (found)
$expireDays[] = $data[array_search position]['cnt'];
else
$expireDays[] = 0;
This means that you remove the $expireDays from your first loop.
Finally, perhaps I have misunderstood and that your 'days' column shouldn't match your $stamp dates as those dates are in the future and your 'days' columns are in the past. In this case, your only option is to adjust your sql statement to forcibly include dates that are missing (between a certain date range)
Good luck.

Inserting range of dates in mysql db

I have a mysql database in which I am trying to insert consecutive dates for one year (starting 7-1-2012) and only want weekday dates inserted using php. Below is the code I have so far but get an error message: unexpected 'Y' (T_STRING) at the "values (date("Y-m-d", $i)" code on line 11. Any help is greatly appreciated.
$startdate = mktime(0,0,0,7,1,2013);
$enddate = strtotime("+1 years", $startdate);
// now we have a lower number and an upper
// number, we can loop to give dates
echo $startdate;
echo $enddate;
for($i=$startdate; $i<=$enddate; $i=strtotime("+1day",$i)) {
if ($i >=2 && $i<=6){
$insert_query = "insert into schedstats(schedDate, schedRep, reqPOD) values (date("Y-m-d", $i), 2, "All Day")";
mysql_query($insert_query) or die ("Error in query: $insert_query. ".mysql_error());
}
}
You either need to use the opposite quote style inside your other quote style, or escape your quotes, like \" or \', within a String. You should also use MySQL DATE AND TIME FUNCTIONS within MySQL.
$insert_query = "insert into schedstats(schedDate, schedRep, reqPOD) values (date("Y-m-d", $i), 2, "All Day")";
should be something like:
$insert_query = "INSERT schedstats(schedDate, schedRep, reqPOD) VALUES (DATE_FORMAT(FROM_UNIXTIME($i), '%Y-%m-%d'), 2, 'All Day')";
See http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html for more details.
Side Note:
Variables, like $i will be evaluated inside double quotes. Single Dimensional Numeric Arrays can also be evaluated in double quotes, like "What $ary[1] more info here";. If you want to put a Single Dimensional Associative Array inside double quotes, that can be done like "What {$ary['key']} more info here";. If you are putting another String inside a String, imagine that the String your putting in's quotes are being pealed off. So, if the quotes themselves need to be in the String you're putting the other String into, put them back on. If you can't get your results through any of the double quote methodologies, use concatenation, like 'What '.$ary[0]['key'].' more info here';. Since PHP will try and evaluate everything inside double quotes it may be technologically faster to use single quotes. I use double quotes all the time and it works fine, though.
mysql> SELECT ADDTIME('2007-12-31 23:59:59.999999', '1 1:1:1.000002');
-> '2008-01-02 01:01:01.000001'
mysql> SELECT ADDTIME('01:00:00.999999', '02:00:00.999998');
-> '03:00:01.999997'
Source: dev.mysql.com: function_addtime
The reason you are not getting any element inserted, is that you were checking the var $i to be between 2 and 6 (Monday and Friday?). The point is that $i is initialized to a unixtime timestamp, and that's a very high value.
First I did, was to rename $i as $tstamp, so it's more clear what it really is. Then the function isWeekDay() checks whether $tstamp is a weekday. Finally, as schedDate is a DATE field, you need to convert $tstamp from a unixtimestamp to a MySQL Date.
NOTE: According to PHP docs, weekdays ranges between 1 and 5.
<?
$startdate = mktime(0,0,0,7,1,2013);
$enddate = strtotime("+1 years", $startdate);
// now we have a lower number and an upper
// number, we can loop to give dates
echo "startdate: $startdate\n";
echo "enddate: $enddate\n";
for ($tstamp = $startdate; $tstamp <= $enddate;
$tstamp = strtotime("+1day",$tstamp)) {
if (isWeekDay($tstamp)) {
$insert_query = "insert into schedstats(schedDate, schedRep, reqPOD)
values (from_unixtime($tstamp), 2, 'All Day')";
mysql_query($insert_query)
or die ("Error in query: $insert_query. ".mysql_error());
}
}
function isWeekDay($tstamp) {
$weekday = date("w", $tstamp);
return $weekday > 0 && $weekday < 6;
}
?>

Evaluating php code stored in database

I have several strings stored in a database (yes, I know it's not the best practice, but I'm working with a system someone else designed and I cannot change it.)
For example, in my table called specialDates, I have a computedDate column that contains this:
date('d', strtotime("thursday, november ".date("Y")." + 3 weeks"))
This is pulled into my code and stored in a variable called $request['order_date'].
This, when used in standard PHP code, returns the date that Thanksgiving falls on in the current year. I need to pass the evaluated value of this (for this year - 2013 - the value is 28) to another query. But I can't seem to get the value to evaluate.
$query = 'SELECT count(orderID) as numberOfOrders FROM customer_orders WHERE customerID = ? AND orderDate = ?';
$param = array($request['customer_id'], eval($request['order_date']));
doesn't work. And when I just try to echo out the value to the screen, doing this:
echo eval($request['order_date']);
or this:
echo eval(" return \$request['order_date']; ");
just prints out the literal value of the string (i.e. date('d' etc.) rather than the expected evaluated value.
What am I doing wrong?
UPDATED
I tried AScherer's answer below, and although it does work when I just echo the value to the screen:
echo eval(" return {$request['order_date']}; ");
it does not work when I try to use the eval inside my array:
$param = array($request['customer_id'], eval("return {$request['order_date']}"));
How can I get this working so that the value I'm passing in the array is the actual value of 28, rather than the string pre-eval?
You were escaping the $request in your return part, which you dont want to do. This method should work, but id suggest adding return the the row in the database so u dont have to modify the eval
$sql = "SELECT customer_id, CONCAT( 'return ', order_date, ';' ) as function from customer_orders WHERE customerID = ? AND orderDate = ?";
$param = array( $request[ 'customer_id' ], eval( $request[ 'function '] ) );
---
OR
---
$evalData = eval(" return {$request['order_date']}; ");
$param = array($request['customer_id'], $evalData );
Yes, you can change it. If not to a sensible result, then to a useful result nontheless.
Your input data is a string:
date('d', strtotime("thursday, november ".date("Y")." + 3 weeks"))
This is an information to "calculate Thanksgiving of this year". You can set up a lookup table that detects this string and the needed function to execute:
$dateCalculations = array(
'date(\'d\', strtotime("thursday, november ".date("Y")." + 3 weeks"))' => function()
{
return date('d', strtotime("thursday, november ".date("Y")." + 3 weeks"));
}
'date(\'...whatever else is in the system...' => function(){}
// alias names also work
'thanksgiving' => function()
{
return date('d', strtotime("thursday, november ".date("Y")." + 3 weeks"));
}
);
You can then try to find the string from the database in the array and instantly have the function you need to call:
$thanksgiving = $dateCalculations[$dbvalue]();
From here you can go anywhere. Note that this will also work with the alias name "thanksgiving", so you might be able to replace it in the database if you know where else this braindead approach is also used... If not, at least you tried your best.

preg_match for mysql date format

im trying to validate a date to see if it matchs the mysql format
this is the code
$match = "/^\d{4}-\d{2}-\d{2} [0-2][0-3]:[0-5][0-9]:[0-5][0-9]$/";
$s = $this->input->post("report_start"). " " . $this->input->post("report_start_time").":00";
$e = $this->input->post("report_end"). " " . $this->input->post("report_end_time").":59";
if($this->input->post("action") != "")
{
echo trim($s). " => " . preg_match($match, trim($s));
echo "<br>";
echo trim($e). " => " . preg_match($match, trim($e));
}
the date format goes into $s and $e are
$s = 2011-03-01 00:00:00
$e = 2011-03-01 23:59:59
and they both return false (0).
i tested the pattern on http://www.spaweditor.com/scripts/regex/index.php and it returns true (1)
http://pastebin.com/pFZSKYpj
however if i manual inter the date strings into preg_match like
preg_match($match, "2011-03-01 00:00:00")
it works.
i have no idea what im doing wrong
======================
now that i think about it, i only need to validate the houre:min part of the datetime string.
im manually adding the seconds and the date is forced by a datepicker and users cant edit it
You're making your work harder that it needs to be. In php there are many date handling functions that mean you don't have to treat dates like strings. So, rather than test that your input dates are in the correct format, just insist on the correct format:
$adate= date_create('January 6, 1983 1:30pm'); //date format that you don't want
$mysqldate= $adate->format("Y-m-d h:i:s");//date format that you do want
There are also functions to check that a date is a real date, like checkdate.
ok heres wat i did.
since im forcing the date format and the ending seconds of the time part
i just validated the hour:mini part using "/^2[0-3]|[01][0-9]:[0-5][0-9]$";
and if that returns true i put everything together end reconstructed the final datetime string
$match = "/^2[0-3]|[01][0-9]:[0-5][0-9]$/";
$s_d = $this->input->post("report_start");
$s_t = $this->input->post("report_start_time");
$e_d = $this->input->post("report_end");
$e_t = $this->input->post("report_end_time");
if($this->input->post("action") != "")
{
if(
( preg_match($match , trim($s_d." ".$s_t.":00")) )
&& ( preg_match($match , trim($e_d." ".$e_t.":59")) )
)
{
$r = $this->model_report->client_hours_logged(array($s,$e));
$data['report'] = $r;
var_dump($r);
//$this->load->view("report/client_hours_per_client",$data);
}
}
Watch out:
[0-2][0-3] is not a good regex for hour values - it will match 01, 12, 23 and others, but it will fail 04 through 09 and 14 through 19.
Better use (2[0-3]|[01][0-9]) instead.
I use this to validate a 'Y-m-d H:i:s' format date string:
match = '/^[12][0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[01]) ([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/';
You could use strtotime and date to parse and format the date properly.
Why not just simply force the date into the format you want:
$e = '2011-03-01 00:00:00';
$mysqlFormat = date('Y-m-d H:i:s', strtotime($e));
Also, there is a bit of an error in your regex [0-2][0-3]:[0-5][0-9]:[0-5][0-9] will only match the hours of 00,01,02,03,10,11,12,13,20,21,22,23 so it will never match 4am, or 3pm among others. That aside I looked over your RegEx and I don't see any problems with it matching the test cases you've offered. I would check to make sure there is not extra whitespace on either side of date string with trim().
I concur with Tim : MySQL behaves in quirks mode and always tries to go easy on DATE and DATE_TIME column types. You can omit certain parts of your input and it still will try to compensate and achieve that goal successfully to some degree... That's why, most numbers your Reg-ex considers as invalid, MySQL will accept as valid.

Categories