Reading date from uploaded Excel file - php

I am uploading an Excel file through PHP Excel. The column C has dates in format mm/dd/yyy.
When I echo the date for example '10/3/2016' it reads it as 42646. The format set for the column is short Date.
How can I read it as the normal date instead of 42646.
here is the model
function fi_upload($file_name){
$file = './uploads/'.$file_name;
$this->load->library('excel');
$objPHPExcel = PHPExcel_IOFactory::load($file);
$cell_collection = $objPHPExcel->getActiveSheet()->getCellCollection();
foreach ($cell_collection as $cell) {
$column = $objPHPExcel->getActiveSheet()->getCell($cell)->getColumn();
$row = $objPHPExcel->getActiveSheet()->getCell($cell)->getRow();
$data_value = $objPHPExcel->getActiveSheet()->getCell($cell)->getValue();
if ($row == 1) {
$header[$row][$column] = $data_value;
} else {
$arr_data[$row][$column] = $data_value;
}
}
$data['header'] = $header;
$data['values'] = $arr_data;
$datecell = $objPHPExcel->getActiveSheet()->getCell('P2');
if(PHPExcel_Shared_Date::isDateTime($datecell)) {
$InvDate = date($format="Y-m-d", PHPExcel_Shared_Date::ExcelToPHP($datecell));
}
echo $InvDate;
exit();
foreach ($arr_data as $q){
echo $q['C']; // column of date, date is echoed as 42646
exit(); //here i exit to display the date
}
I have to later insert it in the database as well in the yyyy/mm/dd format (which I can do if it is read properly)
Thanks.
UPDATE:
So apparently it was an Excel file issue, not php. Converting the cell values through TEXT() was the solution as suggested by #Hallur.
UPDATE 2.0:
I am trying to do it via PHPEXCEL method but I get the following two issues.
: Object of class PHPExcel_Cell could not be converted to int
Echoes date as 2036-02-07 where as the date in cell is 10/4/2016

42646 is an MS Excel serialized timestamp value, the number of days since 1st January 1900 (or 1st January 1904, depending on whether the spreadsheet is using the Windows or Mac calendar)
PHPExcel provides a variety of functions to convert values between MS Excel serialized timestamps and Unix timestamps or PHP DateTime objects (or vice versa), all of which can be found in the PHPExcel_Shared_Date class, e.g.
ExcelToPHP() to convert an MS Excel serialized timestamp to a unix timestamp
ExcelToPHPObject() to convert an MS Excel serialized timestamp to a PHP DateTime object
Alternatively, using the getFormattedValue() method instead of getValue() will return a formatted date/time string value instead of the serialized tiemstamp

$field1= $objWorksheet->getCellByColumnAndRow(0,$i)->getFormattedValue(); //Excel Column 3
$date = PHPExcel_Shared_Date::ExcelToPHP($field1); //unix
echo $field1= gmdate("Y-m-d", $date); //date
Already wrote answer this link

The answer to this question is here:
Excel weird behaviour with dates => text
The number 42646, is the amount of days since january 1st year 1900.
To convert the excel base date to unix time ( time() ), you must calculate the difference between unix start to excel base time start. (unix start: d-m-Y H:i:s -> 01-01-1970 01:00:00) (excel start: d-m-Y -> 1-1-1900)
First to get the difference, which is approximately 70 years and 1 hour (+ 1 extra day because excel date 1-1-1900 = 1, not 0.)
70 years, 1 day, 1 hour = 70 years + 25 hours. (to make up for leap years, we have to say 365.25 instead of 365 days in a year)
(70*365.25*24*60*60)+(25*60*60)
Now, we need to convert the excel date value to seconds as well: 42646*24*60*60 (~ 116 years)
We need to subtract them from each other to get the unix time, and since the excel date is higher than the 70 years, we put that first.
to echo out the day:
echo date("d-m-Y", (42646*24*60*60) - ((70*365.25*24*60*60)+(25*60*60)));
EDIT: I just realized that extra hour is because of my timezone.. CET, not UTC.

Related

PHP - How to compare file modification date with current date

I want to compare the file modification date with the current date.
I tried the following (which is working for the current Time):
$currentDay = date("d");
$currentMonth = date("m");
$currentYear = date("y");
$currentHour = date("h");
$currentMinute = date("i");
Now i tried to get the file modification year from my file:
$subst1 = file("f1/subst_001.htm");
$mod_date=date("y", filemtime($subst1));
echo $mod_date;
But it's giving me for year "70", which is coming from the Year 1970, what did i do wrong?
And no, i already checked if the file says this creation year...
The filetime() function expects string as file path. Here you are trying to pass an array that is returned from file()
Try like this way,
$filename= "f1/subst_001.htm";
if (file_exists($filename)) {
$mod_date = date("y", filemtime($filename));
echo $mod_date;
}
January 1, 1970 is the so called Unix epoch. It's the date where they
started counting the Unix time. If you get this date as a return
value, it usually means that the conversion of your date to the Unix
timestamp returned a (near-) zero result. So the date conversion
doesn't succeed. Most likely because it receives a wrong input.
Courtesy : Oldskool
Use the correct date format parameter.
'y' returns a two digit representation of the year:
date ("y", filemtime($filename)) // 18
'Y' returns the four digit representation of the year:
date ("Y", filemtime($filename)) // 2018
Try this:
$mod_date=date("y", filemtime("f1/subst_001.htm"));
echo $mod_date;
filemtime() takes string:pathname as its parameter but file() function reads a file into an array. Hope that helps.
Try using var_dump on the filemtime result - it is probably false (or something which converts to int 0). Since time 0 is January 1, 1970, that would explain why the year is '70'.
If that's the case, it's not finding your file.

Phpexcel getting wrong date

I am using phpexcel to import excel document to website. I have problem with getting Date format.
Date format is dd.mm.Y but after getting cellValue I get samo random numbers ( float(42391) )
This is my code:
$datum = $objPHPExcel->getActiveSheet()->getCell('A'.$i)->getValue();
this shoud get date?
$file_name = clean_uri($_FILES['excel']['name']);
$file_name = 'povijest_'.$file_name;
$folder_s = 'upload_data/excel';
move_uploaded_file($_FILES['excel']['tmp_name'], '../'.$folder_s.'/'.$file_name);
$objPHPExcel = PHPExcel_IOFactory::load('../'.$folder_s.'/'.$file_name);
$allDataInSheet = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
$highestColumm = $objPHPExcel->getActiveSheet()->getHighestColumn();
$colNumber = PHPExcel_Cell::columnIndexFromString($highestColumm);
$arrayCount = count($allDataInSheet);
for($i=4;$i<=$arrayCount;$i++){
$datum = $objPHPExcel->getActiveSheet()->getCell('A'.$i)->getValue();
$prva = $objPHPExcel->getActiveSheet()->getCell('C'.$i)->getValue();
$zadnja = $objPHPExcel->getActiveSheet()->getCell('D'.$i)->getValue();
$najvisa = $objPHPExcel->getActiveSheet()->getCell('E'.$i)->getValue();
$najniza = $objPHPExcel->getActiveSheet()->getCell('F'.$i)->getValue();
$prosjecna = $objPHPExcel->getActiveSheet()->getCell('G'.$i)->getValue();
$promjena = $objPHPExcel->getActiveSheet()->getCell('H'.$i)->getValue();
$broj_transakcija = $objPHPExcel->getActiveSheet()->getCell('I'.$i)->getValue();
$kolicina = $objPHPExcel->getActiveSheet()->getCell('J'.$i)->getValue();
$promet = $objPHPExcel->getActiveSheet()->getCell('K'.$i)->getValue();
var_dump($datum);
exit;
It does get the date..... that isn't a random number, that's an MS Excel serialized datetime stamp. In the same way that you might use a unix timestamp in PHP, and then use the date() function to format that, MS Excel uses its own timestamp value, which is a count of the number of days since 1st January 1900 (or 1st January 1904 if created on a Mac). To display it formatted, you need to apply a number format mask.
The Cell's getValue() method will return the raw value from the cell, but getFormattedValue() will return the value with the number format mask applied
There are also documented methods (e.g. PHPExcel_Shared_Date::ExcelToPHP($msExcelSerializedTimestamp)
) for converting between the MS Excel timestamp and unix timestamp or DateTime objects, and for checking whether a cell contains a date or not

convert excel dateserial back to a readable date format

How do i convert this excel dataserial value 41225 back to date format 12-Nov-2012 using phpexcel and code igniter?
I have tried the following but it didn't work.
$G74 = $objPHPExcel->getActiveSheet()->getCell('B6')->getValue();
Dates in Excel are stored as number of days since 1st Jan 1900, except there is an off by one error due to 1900 not being a leap year. You can create therefore a DateTime object with this hack (valid for dates from 1st March 1900 onwards):
$n = 41225;
$dateTime = new DateTime("1899-12-30 + $n days");
You can format the DateTime Object with something like:
echo $dateTime->format("d M Y");
If you want to include the time as well as the date, multiply by 86400 (the number of seconds in a day) to get seconds since 1st Jan 1900 before you convert:
$n = 42898.35416666;
$dateTime = new DateTime("1899-12-30 + ". round($n * 86400) . " seconds");
Using the getFormattedValue() method rather than getValue() might help if the cell has a format mask that formats it as a date. getValue() returns a raw value, which (in this case) is the Excel serialized number.
Otherwise, the ExcelToPHP() or ExcelToPHPObject() methods in the PHPExcel_Shared_Date class should do the job of returning a unix timestamp or a PHP DateTime object that you can then format however you wish
I had to convert a dateserial number in decimal format ie: 42898.35416666 and the DateTime object does not take decimals.
Based on rjmunro's answer, and animuson's answer on how to convert decimals to hours and minutes, here is a solution for decimal Excel dates.
function dateSerialToDateTime($dateserial) {
$arrDate = explode(".", $dateserial);
$n = $arrDate[0];
$decimal = "." . $arrDate[1]; //decimal amount of seconds
$duration = 86400 * $decimal; //number of seconds in a day * decimal
$dateTime = new DateTime("1899-12-30 + $n days");
$converted = $dateTime->format("Y-m-d") . " " . gmdate("H:i:s", $duration);
return $converted;
}
$dateserial = 42898.35416666;
die(dateSerialToDateTime($dateserial));
//returns 2017-06-12 08:29:59

Mismatch when converting Excel date numbers to Unix Timestamp using PHP

Hi~ I am using PHPExcel 1.7.7 to read XLSX files and present the results in web pages.
I'm trying to get the value of a cell that stores a date & time string and process it in PHP using the following code.
<?php
date_default_timezone_set('Australia/Canberra');
$value = $objPHPExcel->getActiveSheet()->getCell('A1')->getValue();
define('MIN_DATES_DIFF', 25569);
define('SEC_IN_DAY', 86400);
function excel2Timestamp($excelDate)
{
if($excelDate <= MIN_DATES_DIFF)
{
return 0;
}
return ($excelDate - MIN_DATES_DIFF) * SEC_IN_DAY;
}
echo $result = date('H:i:s d/m/Y', excel2Timestamp($value));
?>
while the original value in the cell is "00:00:00 01/07/2012", instead of giving me the correct results, the output from the above PHP code shows "10:00:00 01/07/2012".
It seems that it is caused by the time zone differences, but I have already defined the time zone at the beginning of the code. No idea what is wrong with it.
Can anyone please help me with it? Thanks in advance.
Forget your function to convert to timestamp (I was doing the same too)... PHPExcel does the convertion automatically, so try doing this:
//get the excel date value (if it's stored in the A1 cell)
$excelDate = $objPHPExcel->getActiveSheet()->getCell('A1')->getValue();
//converts from excel format to a datetime object
$date = PHPExcel_Shared_Date::ExcelToPHPObject($excelDate);
//format the date as you want.
$formatedDate = $date->format('m/d/Y');
It should work.

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