php format date pre 1970 fro MySQL insert - php

I am importing data from a CSV file and one column has a list of dates. Some of these dates are pre 1970. An example date would be 10/03/1956
I've got a problem in formatting these dates into a format that I can insert into MySQL.
if i use this
$date = DateTime::createFromFormat('d/m/Y', $col[8]);
I get this error message
Call to a member function format() on a non-object
but if I hard code a date like this, it works
$date = DateTime::createFromFormat('d/m/Y', '21/03/1966');
here is the complete code
$inputFileName = 'data.csv';
if (($handle = fopen($inputFileName, "r")) !== FALSE) {
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
for ($i = 0; $i < $num; $i++) {
$col[$i] = $data[$i];
}
try {
$date = DateTime::createFromFormat('d/m/Y', trim($col[8]));
}
catch (Exception $e) {
echo $e->getMessage();
exit(1);
}
echo $date->format("Y-m-d");
}
fclose($handle);
}

You have no guarantee that all fields will exist in your CSV file, so you must do a little control
define('DATE_COLUMN', 8);
// #Warning : avoid hard coding file name !
$inputFileName = 'data.csv';
if (($handle = fopen($inputFileName, "r")) !== FALSE) {
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
for ($i = 0; $i < $num; $i++) {
$col[$i] = $data[$i];
}
$dateString = NULL;
if (isset($col[DATE_COLUMN]) &&
strlen(trim($col[DATE_COLUMN])) > 0) {
$dateString = trim($col[DATE_COLUMN]);
}
if (is_null($dateString)) {
// print log or throw an exception if you want
}
else {
try {
$date = DateTime::createFromFormat('d/m/Y', dateString);
echo $date->format("Y-m-d");
}
catch (Exception $e) {
echo $e->getMessage();
exit(1);
}
}
}
fclose($handle);
}

Related

How to throw custom exception in php while parsing csv files?

I'm writing php code to parse a csv file. I have to validate the basic data type for all the fields in the csv fileds and should throw an instance of a CsvParserException if there is any broken data in the csv file. I've given a generic exception but I want to give a custom exception which is an instance of CsvParserException.
Below is my code. I'm not sure how to to properly handle this.
<?php
namespace app;
class CsvParser{
public function parse() {
$row = 1;
$flag = true;
if (($handle = fopen("file.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
echo $num;
$row++;
if($flag) { $flag = false; continue; } // this is to skip the first line
for ($c=0; $c < $num; $c++) {
echo "data[0] is = ". $data[0] . " data[c] is = ". $data[$c]. " <br />\n";
if(!((isset($data[0])) && (is_numeric($data[0])))) {
throw new \Exception('Id is not valid');
}
if(!((isset($data[1])) && (is_string($data[1])))) {
throw new \Exception('This is not a valid string. ');
}
if(!((isset($data[2])) && (is_string($data[2])))) {
throw new \Exception('This is not a valid string. ');
}
$date = strtotime($data[3]);
$splitData = explode('|', $data[4]);
foreach($splitData as $value) {
if(!((isset($value)) && (is_numeric($value)))) {
throw new \Exception('Integers is not valid');
}
}
}
}
fclose($handle);
}
}
}
?>
Can someone please help ?

Getting a CSV cell full value in PHP

Am reading a CSV file using PHP, i get all the values for each row but some columns having long data displays something like this 9.21008E+15
I don't know how to get the complete value which is suppose to be this 9210080000000000
if (($handle = fopen("Test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
$num = count($data);
$tb_row = "";
for ($c=0; $c < $num; $c++) {
$tb_row .= $data[$c].",";
}
$new_row = substr($tb_row, 0, -1);//removing the comma at the end of line...
//explode and assign values then insert
$each_col = explode(',', $new_row);
$Device_state = $each_col[0];
$udid = $each_col[8];
$imsi = $each_col[9];
$imei = $each_col[10];
echo "$imsi || $imei"."<br />";
}
}
Adding a prefix to the cells having this issue solved the issue (')
You need just convert it back into integer value
if (($handle = fopen("Test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
$num = count($data);
$tb_row = "";
for ($c=0; $c < $num; $c++) {
if (strpos($data[$c], 'E+'))
$data[$c] = intval((float)$data[$c]);
$tb_row .= $data[$c].",";
}
$new_row = substr($tb_row, 0, -1);//removing the comma at the end of line...
//explode and assign values then insert
$each_col = explode(',', $new_row);
$Device_state = $each_col[0];
$udid = $each_col[8];
$imsi = $each_col[9];
$imei = $each_col[10];
echo "$imsi || $imei"."<br />";
}
}

very slow php script

When I run the code it is ridiculously slow even if I comment out the second half where I fopen the same file. I have changed the length of stream_get_line. File is 64MB, 73500 lines, 159 columns. Any help to optimize would be much appreciated.
<?php
include "configure.php";
$row = 1;
if(($handle = fopen("ACC_half.txt", "r")) !== false)
{
global $arraySamples;
global $arrayTrans;
global $num;
global $lines;
while (!feof($handle))
{
$data = stream_get_line($handle, 1000000, "\n");
$num = count($data);
$lines = count(file("ACC_half.txt"));
//Get all the names of the samples into array
if($row == 1)
{
for($i=0;$i<$num;$i++)
{
//echo $data[$i];
$arraySamples[]=$data[$i];
}
//Get all the names of the first row(headers) into array for use
}
else
{
$arrayTrans[]=$data[0];
}
$row++;
}
}
fclose($handle);
$row = 1;
$transInc=1;
if(($handle1 = fopen("ACC_half.txt", "r")) !== false)
{
while (($data2 = stream_get_line($handle,1000000,"\n\r")) !== false)
{
if(($row == 2) || ($row==1))
{
$row++;continue;
}
$jnum=count($data2);
for($j=1;$j<$jnum;$j+=2)
{
$g=$j+1;
$h=$j+2;
$import = mysql_query("INSERT into acc (form,sample,raw,scale)
VALUES ('$arrayTrans[$transInc]', '$arraySamples[$g]', '$data2[$j]', '$data2[$g]')")
or die (mysql_error());
}
$transInc++;
}
}
fclose($handle1);
?>
I believe that one of the main problems is that you open the same big file twice. You should open this file once not twice

SQL being executed twice in FOR loop

I think I need a second pair of eyes on this one. For the life of me I can't figure out why my SQL INSERT query is running twice every iteration:
if (($handle = fopen($spreadsheet_url, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($current_row == 1 || $current_row == 2) {
$num = count($data);
//echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
//echo $data[$c] . "<br />\n";
try {
set_time_limit(0);
$stmt = $db_temp_kalio->prepare('INSERT INTO invupdate (sku,prod) VALUES(:sku, :prod)');
$stmt->execute(array(':sku'=> $data[0], ':prod'=> $data[1])); }
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
exit; }
}
}
$current_row++;
}
fclose($handle);
}
Well, I probably should have put forth a little more effort before asking for assistance. I was able to fix this by adding a row reset counter in the loop:
if (($handle = fopen($spreadsheet_url, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($current_row == 1 || $current_row == 2) {
$row_reset = 0;
$num = count($data);
//echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
//echo $data[$c] . "<br />\n";
if ($row_reset == 0) {
try {
set_time_limit(0);
$stmt = $db_temp_kalio->prepare('INSERT INTO invupdate (sku,prod) VALUES(:sku, :prod)');
$stmt->execute(array(':sku'=> $data[0], ':prod'=> $data[1])); }
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
exit; }
}
$row_reset++;
}
}
$current_row++;
}
fclose($handle);
}
I'm still curious if there is a better way.
I looks like you were using some code to iterate through your columns, but actually only have two, containing the sku and prod ($data[0] and $data[1].) If that is the case, then you don't need the for loop inside. (BTW, it was that loop that was causing the query to be executed twice, as the query was inside it.) It also looks like you have two counters going for the row (current_row and row) so those can be combined. If you are using the if ($currentRow == 1... statement to ignore the header on row 0 and then only process 2 rows, you will want to switch it to if ($currentRow > 0) when you are ready to run the whole spreadsheet. Using break in the catch clause instead of exit will cause the code to drop out of the while loop and hit the fclose statement:
if (($handle = fopen($spreadsheet_url, "r")) !== FALSE) {
$currentRow = 0;
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if ($currentRow == 1 || $currentRow == 2) {
$num = count($data);
//echo "<p> $num fields in line $currentRow: <br /></p>\n";
//echo "<p> The data for this row is: " . $data[0] . " " . $data[1] . "\n";
try {
set_time_limit(0);
$stmt = $db_temp_kalio->prepare('INSERT INTO invupdate (sku,prod) VALUES(:sku, :prod)');
$stmt->execute(array(':sku'=> $data[0], ':prod'=> $data[1]));
}
catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
break;
}
}
$currentRow++;
}
fclose($handle);
}

formatting fgetcsv output

Im trying to figure out how to take the data returned by fgetcsv, and format it into a readable/editable table, and then use fputcsv to save that table
so far i have this
<?php
$row = 1;
$handle = fopen("csv.csv", "r");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "\n";
}
}
fclose($handle);
?>
The following code will output the CSV in an html table. To make it editable wrap the echo ..$val.. with tags and add a php form handler that takes the result and reforms a CSV
<?php
$row = 1;
$handle = fopen("csv.csv", "r");
echo("<table>");
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
echo("<tr>\r\n");
foreach ($data as $index=>$val) {
echo("\t<td>$val</td>\r\n");
}
echo("</tr>\r\n");
}
echo("</table>");
fclose($handle);
?>

Categories