Multidimensional array with different keys to format data - php

I have multidimensional dynamic array with following structure
$xData["invoice"]["no"]["data"] = "DY-13123";
$xData["invoice"]["date"]["data"] = "01-08-2018";
$xData["invoice"]["total_due"]["data"] = 56890.23;
$xData["invoice"]["due_date"]["data"] = "01-12-2018";
$xData["from"]["name"]["first"]["data"] = "Company Name, Inc";
$xData["from"]["address1"]["data"] = "12345 Sunny Road";
$xData["from"]["address2"]["data"] = "Sunnyville, CA 12345";
I want to allow users to format the data of array by specifying format. For example $xData["invoice"]["date"]["data"]= "01-08-2018"
for this, user can specify the format as date type and formatting as "YYYY-mm-dd". I am storing this format information in another array.
$xFormat["invoice"]["date"] = array("date","YYYY-mm-dd");
$xFormat["invoice"]["total_due"] = array("currency","$");
Now, I need to get the value of $xData and apply the formatting. I have tried getting all keys and applying the format but no success. Please let me know how
to do this.
Thanks in advance

What you need to do is, first take the string in date field and convert it to time, then format it with the format in $xFormat
$time = strtotime($xData["invoice"]["date"]["data"]); //converting the date in string to seconds since January 1 1970 00:00:00 UTC
if ($time === false) { //if the date couldn't be converted to seconds
echo "date is wrong";
} else {
echo date($xFormat["invoice"]["date"]["date"],$time); //yes, double date fields is correct
}
The function strtotime converts a string representation of a time to seconds, which in turn can be used in date. Since you have set $xFormat["invoice"]["date"] as array("date","YYYY-mm-dd"), I had to use $xFormat["invoice"]["date"]["date"]

Related

Custom date format in PHPExcel

In my excel file I am building from PHP the first row is the header one. I need to put there several dates as column header. Each date is (in dd/mm/yyyy format) 15/mm/yyyy starting from 15/01/2007 and ending with 15/12/2018 stepping month by month.
My code is this:
for($anno = $annoMin; $anno<=$annoMax; $anno++){
for($mese = 1; $mese <= 12; $mese++){
$mese = sprintf("%02s", $mese);
$periodo = '15/'.$mese.'/'.$anno;
$periodo = strtotime($periodo);
$periodo = PHPExcel_Shared_Date::PHPToExcel($periodo);
array_push($header_array,$periodo);
}
}
I build the date as a string, convert it into a unix timestap, convert it into an excel date and push it into the $header_array.
Then I draw the cells in the excel:
$ews->fromArray($header_array, ' ', 'A1');
Finally I format the cells where there is a date as:
$ews->getStyle('U1:EJ1')
->getNumberFormat()
->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY);
ISSUES ARE:
Actually my code is returning 'False' for each cell with a date;
I need to add a custom mask that is not listed in the PHPExcel library: MM/YYYY to be shown in each cell.
For the first issue: I have checked different SO questions and followed mainly this one. with no luck.
Problem is here:
$periodo = '15/'.$mese.'/'.$anno;
$periodo = strtotime($periodo);
which would give a string values of 15/1/2015, 15/2/2015... ``15/12/2015that you're then attempting to convert to a unix timestamp usingstrtotime()`.
If you read the PHP Docs on date formats used by the strtotime() function, you'll see that a / separator tells PHP that the date string is US date format.... i.e. mm/dd/yyyygiving a month value of15` in every case, and (of course) there is no month 15
Either use a dash (-) rather than a / to indicate European (dd-mm-yyyy) rather than US date format
$periodo = '15-'.$mese.'-'.$anno;
$periodo = strtotime($periodo);
or re-order the values to use US format
$periodo = $mese.'/'.'15/'.$anno;
$periodo = strtotime($periodo);
And for the second part of your question.... you can supply almost any format mask that MS Excel recognises, you're not restricted to the built-in formats; so:
$ews->getStyle('U1:EJ1')
->getNumberFormat()
->setFormatCode('mm/yyyy');
The format code is simply a string value

Adding leading zeroes to a string date in PHP

I have a string "date" which can be DD.MM.YYYY or D.M.YYYY (with or without leading zeros), it depends what a user types.
Then I use it in a condition to send another email when the day is today.
if($_POST["date"]== date("d.m.Y")){
$headers.="Bcc: another#mail.cz\r\n";
}
The problem is that the mail is send when the date format DD.MM.YYYY (with leading zeros) only.
My proposed solution
As I'm not very good in PHP, I only know the solution theoretically but not how to write the code - I would spend a week trying to figure it out on my own.
What's in my mind is dividing the date into three parts (day, month, year), then checking the first two parts if there's just one digit and adding leading zeros if it's the case. I don't know how to implement that to the condition above, though. I have read a few topics about how to do this, but they were a bit more different than my case is.
You should equalize to same format d.m.Y and you can do this with strtotime and date function:
$post_date = date("d.m.Y", strtotime($_POST["date"]));
if($post_date == date("d.m.Y")){
$headers.="Bcc: another#mail.cz\r\n";
}
I changed date to $post_date for more clear. I'll try to explain difference with outputs
echo $_POST["date"]; // lets say: 8.7.2013
echo date("d.m.Y"); // 09.09.2013 > it's current day
strtotime($_POST["date"]); // 1373230800 > it's given date with unix time
$post_date = date("d.m.Y", strtotime($_POST["date"])); // 08.07.2013 > it's given date as right format
If you use date function without param, it returns as current date.
Otherwise if you use with param like date('d.m.Y', strtotime('given_date'));, it returns as given date.
$post_date = date("d.m.Y", strtotime($_POST["date"]));
At first, we converted your date string to unix with strtotime then equalized and converted format that you used in if clause.
first set date format with leading Zero
$postdate = strtotime('DD.MM.YY', $_POST['date']);
and also matching date will be in same format
$matching_date = date('DD.MM.YY', strtotime('whatever the date'));
then
if ( $postdate === $matching_date )
{
// send mail
}
Why don't you just check the length of the _POST (it can be either 8 or 10)
if (strlen($_POST["date"]) == 10) {
$headers.="Bcc: another#mail.cz\r\n";
}

Generate a data-time format from 2 separated strings

I need to compare date/time that I get from MySQL with a format like: 2013-05-17 15:07:29
From another database, I have data and time separated and in the notation: 130998 081836
I have concatenated the two strings to get only one and I'm trying to convert it to my desired format using:
$dateTimeNmea = $array[9]." ".$array[1]; // 130998 081836
$dateTime = date("Y-m-d H:i:s", $dateTimeNmea); // 1970-01-02 13:23:18
So "it works" on the format but the values are wrong. It could be 1998-09-13 08:18:36
Where is my fault?
It has format siH dmy. Try date_parse_from_format('siH dmy', $string) to get it in array.
130998 081836 is not a format for a date that the date function can understand.
For starters the date() function expects the second param to be a timestamp (read docs for it here)
Then you would need to parse the string into a useable date format via date_parse_from_format and finally into a timestamp
Something like
$string = '130998 081836';
$date = date_parse_from_format('dmY His', $string);
$dateString = date('Y-m-d H:i:s', strtotime(vsprintf('%s-%s-%s %s:%s:%s', $date)));
var_dump($dateString); // var dump just for output/test
The strtotime(vsprintf('%s-%s-%s %s:%s:%s', $date) formats your parsed date into a timestamp which can then be used in date methods second param to get exactly the format you need.

php search date with different format

At my current database i use date format yyyy-mm-dd.
If i want to search by DOB then must use format yyyy-mm-dd to match it with default date format.
Is there a way to search DOB from whatever user input wether its dd-mm-yyyy or dd/mm/yyyy or yyyy-mm-dd and give out the result???
$keyword = clean($keyword,1);
$result = $db->query("SELECT name, dob, email FROM user WHERE name LIKE '$keyword%' OR dob LIKE '$keyword%' OR email LIKE '$keyword%'");
if($result){
//echoing the result
}
Not easily. First convert the user input to the correct format before passing it to the SQL query.
For example:
if (preg_match('~([0-9]{2})[-/]([0-9]{2})[-/]([0-9]{4})~', $input, $matches)) {
return $matches[3].'-'.$matches[2].'-'.$matches[1];
} else {
return $input;
}
You could match UNIX Timestamps eg:
$timestamp = strtotime($date)
SELECT * WHERE UNIX_TIMESTAMP(dob) = '$timestamp'
Check http://php.net/manual/en/function.strtotime.php for more info on strtotime()
This will make it easier for checking within a date range.
Yes, you should normalise the result in PHP before passing it to your SQL query.
Your code may look something like this...
$dateForSqlQuery = date('Y-m-d', strtotime($input));
...assuming that strtotime() will correctly handle those variations.
On the other hand, you should really break up the user input into a separate day, month and year input, then generate the string yourself.
You can use strtotime to parse pretty much any (reasonably formatted) date to a timestamp, and from there you can convert to any other format.
For example:
$yyyy_mm_dd = date('Y-m-d', strtotime('02/01/2012'));
It's quite a processor heavy function though, strtotime, so do be sparing!

Optional month or day in MySQL date field from PHP

I have a problem where I need to handle dates where the month and day parts are optional. For example, the year will always be known but sometimes the day or month and day will be unknown.
In MySQL I can create a table with a date field and while I can't find any reference in the MySQL Manual it will accept the following as valid:
(YYYY-MM-DD format):
2011-02-10 // Current date
2011-02-00 // Day unknown so replaced with 00
2011-00-00 // Day and month unkown so replaced with 00-00
Test calculations from within the database work fine so I can still sort results easily. In the manual it says that month needs to be between 01 and 12, and day between 01 and 31 - but it does accept 00.
First question: Am I going to run into trouble using 00 in the month or day parts or is this perfectly acceptable?
Next question: Is there a PHP function (or MySQL format command) that will automatically format the following dates into the required format string?
2011 becomes 2011-00-00
2011-02 becomes 2011-02-00
Or do I need write a special function to handle this?
The following doesn't work:
<?php
$date = date_create_from_format('Y-m-d', '2011-00-00');
echo date_format($date, 'Y-m-d');
// Returns 2010-11-30
$date = date_create_from_format('Y-m-d', '2011-02-00');
echo date_format($date, 'Y-m-d');
// Returns 2011-01-31
?>
Third question: Is there a PHP function (or MySQL command) to format the dates for use in PHP?
Finally, is this the best approach? Or is there a 'best practise' method?
EDIT:
Here is what I'm currently doing:
A date field can accept a date in the format YYYY, YYYY-MM, or YYYY-MM-DD and before sending to the database it is processed in this function:
/**
* Takes a date string in the form:
* YYYY or
* YYYY-MM or
* YYYY-MM-DD
* and validates it
*
* Use date_format($date, $format); to reverse.
*
* #param string $phpDate Date format [YYYY | YYYY-MM | YYYY-MM-DD]
*
* #return array 'date' as YYYY-MM-DD, 'format' as ['Y' | 'Y-m' | 'Y-m-d'] or returns false if invalid
*/
function date_php2mysql($phpDate) {
$dateArr = false;
// Pattern match
if (preg_match('%^(?P<year>\d{4})[- _/.]?(?P<month>\d{0,2})[- _/.]?(?P<day>\d{0,2})%im', trim($phpDate), $parts)) {
if (empty($parts['month'])) {
// Only year valid
$date = $parts['year']."-01-01";
$format = "Y";
} elseif (empty($parts['day'])) {
// Year and month valid
$date = $parts['year']."-".$parts['month']."-01";
$format = "Y-m";
} else {
// Year month and day valid
$date = $parts['year']."-".$parts['month']."-".$parts['day'];
$format = "Y-m-d";
}
// Double check that it is a valid date
if (strtotime($date)) {
// Valid date and format
$dateArr = array('date' => $date, 'format' => $format);
}
} else {
// Didn't match
// Maybe it is still a valid date
if (($timestamp = strtotime($phpDate)) !== false) {
$dateArr = array('date' => date('Y-m-d', $timestamp), 'format' => "Y-m-d");
}
}
// Return result
return $dateArr;
}
So it pattern matches the input $phpDate where it must begin with 4 digits, then optionally pairs of digits for the month and the day. These are stored in an array called $parts.
It then checks if months or days exist, specifying the format string and creating the date.
Finally, if everything checks out, it returns a valid date as well as a format string. Otherwise it returns FALSE.
I end up with a valid date format for my database and I have a way of using it again when it comes back out.
Anyone think of a better way to do this?
I have a problem where I need to handle dates where the month and day parts are optional.
For example, the year will always be known but sometimes the day or month and day will be
unknown.
In many occasions, we do need such 'more or less precise' dates, and I use such dates as 2011-04-01 (precise), as well as 2011-04 (= April 2011) and 2011 (year-only date) in archives metadata. As you mention it, MySQL date field tolerates '2011-00-00' though no FAQs tell about it, and it's fine.
But then, I had to interface the MySQL database via ODBC and the date fields
are correctly translated, except the 'tolerated' dates (Ex: '2011-04-00' results empty in the resulting MySQL-ODBC-connected ACCESS database.
For that reason, I came to the conclusion that the MySQL date field could be converted in a plain VARCHAR(10) field : As long as we don't need specific MySQL date functions, it works fine, and of course, we can still use php date functions and your fine date_php2mysql() function.
I would say that the only case when a MySQL date field is needed
is when one needs complex SQL queries, using MySQL date functions in the query itself.
(But such queries would not work anymore on 'more or less precise' dates!...)
Conclusion : For 'more or less precise' dates,
I presently discard MySQL date field and use plain VARCHAR(10) field
with aaaa-mm-jj formated data. Simple is beautiful.
Since the data parts are all optional, would it be tedious to store the month, day, and year portions in separate integer fields? Or in a VARCHAR field? 2011-02-00 is not a valid date, and I wouldnt't think mysql or PHP would be excited about it. Test it out with str_to_time and see what kind of results you get, also, did you verify that the sorting worked right in MySQL? If the docs say that 1 through 31 is required, and it is taking 00, you might be relying on what is, in essence, a bug.
Since 2011-02-00 is not a valid date, none of PHP's formatting functions will give you this result. If it handled it at all, I wouldn't be surprised if you got 2001-01-31 if you tried. All the more reason to either store it as a string in the database, or put the month, day, and year in separate integer fields. If you went with the latter route, you could still do sorting on those columns.
I have also encountered this problem. I ended up using the PEAR Date package. Most date classes won't work with optional months or optional days, but the PEAR Date package does. This also means you don't need custom formatting functions and can use the fancy formatting methods provided by the Date package.
I have found this link in a textbook. This states that month and day values can be zero to allow for the possiblity of storing incomplete or unknown data
http://books.google.co.uk/books?id=s_87mv-Eo4AC&pg=PA145&lpg=PA145&dq=mysql+date+of+death+when+month+unknown&source=bl&ots=tcRGz3UDtg&sig=YkwpkAlDtBP1KKTDtqSyZCl63hs&hl=en&ei=Btf5TbL1NIexhAfkveyTAw&sa=X&oi=book_result&ct=result&resnum=8&ved=0CFMQ6AEwBw#v=onepage&q&f=false
If you pull your date in pieces from the database you can get it as if it's 3 fields.
YEAR(dateField) as Year, MONTH(dateField) as Month, DAY(dateField) as DAY
Then pushing those into the corresponding fields in the next bit of PHP will give you the result you're looking for.
$day = 0;
$month = 0;
$year = 2013;
echo $datestring;
$format = "Y";
if($month)
{
$format .= "-m";
if($day)
$format .="-d";
else
$day = 1;
}
else
{
$month = 1;
$day = 1;
}
$datestring = strval($year)."-".strval($month)."-".strval($day);
$date = date($format, strtotime($datestring));
echo $date; // "2013", if $month = 1, "2013-01", if $day and $month = 1, "2013-01-01"

Categories