convert excel dateserial back to a readable date format - php

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

Related

Convert SQLite to MySQL datetime

I have SQLite DB one table contains datetime field
with datatype "timestamp" REAL value is 18696.0
attach image for table structure
So, I want this 18696.0 value to be converted into MySQL Y-m-d format and result should be 2021-03-10
I have didn't found any solution online. any help would be appreciated.
SQLite timestamp converted into MySQL timestamp.
EDIT: Thankyou for updating your question with the correct number and what date it should represent.
You can achieve what you need with a function that adds the days onto the Unix Epoch date:
function realDateToYmd($real, $outputFormat='Y-m-d')
{
$date = new DateTime('1970-01-01');
$date->modify('+' . intval($real) . ' days');
return $date->format($outputFormat);
}
echo realDateToYmd('18696.0');
// returns 2021-03-10
SQLite dates stored in REAL data type stores dates as a Julian Day.
From https://www.sqlite.org/datatype3.html
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
PHP has a jdtogregorian function, in which one comment has a handy function to convert to ISO8601 dates:
function JDtoISO8601($JD) {
if ($JD <= 1721425) $JD += 365;
list($month, $day, $year) = explode('/', jdtogregorian($JD));
return sprintf('%+05d-%02d-%02d', $year, $month, $day);
}
echo JDtoISO8601('17889.0');
// Results in -4664-11-16
The results don't exactly look right, is it definitely 17889.0 in SQLite?
If this float number 18696.0 represents the number of days since 1970-01-01 then the date can also be calculated like this:
$days = 18696.0;
$dt = date_create('#'.((int)($days * 86400)));
$mysqlDate = $dt->format('Y-m-d'); //"2021-03-10"
background information
Or simply with gmdate:
$mySqlDate = gmdate('Y-m-d',$days*86400);
The days are simply converted into seconds to get a valid timestamp for gmdate.
Try this:
<?php
echo date('Y-m-d H:i:s', 17889);
?>
Output:
1970-01-01 04:58:09

how to convert Integer values into timestamp format?

I have an Integer column "duration_temp" that have values represent the duration in minutes, I want to copy those values in another column "duration" of type timestamp, I'm having the problem of how to convert those Int minutes into timestamps format, for example:
if a value in Int is set to 4 then I should convert it to yyyy-mm-dd 00:04:00.
is there a function that can do that or close from doing that?any suggestion would be appreciate it.
If you have a duration in minutes. You could use DateInterval like this.
$yourDate = new DateTime('2021-01-01 00:00:00');
$durationInMinutes = 4;
$interval = new DateInterval("PT{$durationInMinutes}M");
$yourDate->add($interval);
echo $yourDate->format('Y-m-d H:i:s');
https://www.php.net/manual/en/dateinterval.construct.php
If you mean that you just have minutes and want to make a timestamp from it with current date information, try this (after adding use Carbon\Carbon; in top of you file):
$minutes = 4;
return Carbon::create(now()->year, now()->month, now()->day, 0, $minutes)->toDateTimeString();
As your integer column duration_temp is in minutes, you have to convert it to seconds before you can get the expected result.
Take your example :
Int = 4 minutes => Int = 4 * 60 = 240 second
To finish :
date ("Y-m-d H:i:s", 240); // will give you 1970-01-01 00:04:00
DateTime accepts extensive Relative Formats. This makes possible as an example:
$durationInMinutes = 67;
$date = date_create('2021-01-01 '.$durationInMinutes.' Minutes');
//or $date = new DateTime('2021-01-01 '.$durationInMinutes.' Minutes');
echo $date->format('Y-m-d H:i:s');
//2021-01-01 01:07:00
Also works correctly with negative minute numbers.

UTC time with 7 decimals calculation

I need to calculate the difference between 2 UTC time values with 7 decimals in PHP 7.3
Can I simply do the following:
val1 = 20200205120415.6513380; //first timestamp
val2 = 20200205120415.6535670; //second timestamp
$diff = $val2 - $val1; //should be difference between the 2 timestamps
The value of the above calculation is 0.002229. If I am doing it correctly is that value in seconds or microseconds and will I be able to convert it into a UNIX epoch timestamp?
I strongly suspect that the above times are not simple numbers; they BCD (binary coded decimal) for 2020-02-05-12:04:15.6513380. You can't do simple math on these, and you'll need to parse them to convert to a unix timestamp.
Depending on your language, it may be easiest to parse these by turning them into strings and taking the first four characters as the year, the next two as the month, etc.
Here is my current solution for completeness.
The values on the right of the . is indeed fractional seconds. So in PHP to get the difference I did the following:
$start = 20200205120415.6513380;
$end = 20200205120415.6535670;
//get value left of . and then create datetime object to later convert to seconds
list($datetime, $usecStart) = explode(".", $start);
$startTime = date_create_from_format("YmdHis", $datetime);
list($datetime, $usecEnd) = explode(".", $end);
$endTime = date_create_from_format("YmdHis", $datetime);
//get timestamp in seconds and add franction or microseconds back
$start = $startTime->getTimestamp().".".$usecStart;
$end = $endTime->getTimestamp().".".$usecEnd;
//get difference in seconds and fraction or microseconds
echo $end - $start;
Here is another way using datetime->diff() function:
$start = new DateTime('2020-02-05T12:04:15.6513380Z');
$end = new DateTime('2020-02-05T12:04:15.6535670Z');
$diff = $start->diff($end);
echo $diff->format('%h:%i:%s.%F');

What is the unix timestamp formula?

First of all, i know this question has been sort of asked/sort-of answered here: Calculate day number from an unix-timestamp in a math way? .
I need a custom function/formula for this. so it only returns a ISO format date. "YYYY-MM-DD".
eg. 1316278442 = 2011-09-17
EDIT by Ext!
THIS IS WRONG ! Please don't read this.
I've been at this all day! The only thing i managed to get out is the day of the week.
$dayOfWeek=($timestamp/86400)%7; //And here 1 is Saturday, 7 is Friday
Speed is the issue, that is why i don't want to use date('Y-m-d',$timestamp);
If you cannot help me whit a custom function or formula, at least give me a better explanation on how to do this. It was done in so many languages, there must be someone out there that knows how to do this.
Thank you in advance for your help.
Here is the function that date() and DateTime::setTimestamp() use to compute the date from a unix timestamp:
https://github.com/php/php-src/blob/d57eefe6227081001978c3a63224065af8b5728e/ext/date/lib/unixtime2tm.c#L39
As you can see, this is a bit complicated by leap years, etc.
--
That said, if you need only the day of the week, it seems that you can safely ignore leap years, and just use the formula you given in the question: $dayOfWeek=($timestamp/86400)%7
Ok. The function is complete. It takes a unix timestamp and returns a YYYY-MM-DD. This was all i needed. I hope it helps anyone ...
<?php
$t=1325522004;//return 2011-09-19
/*
* Transform a Unix Timestamp to ISO 8601 Date format YYYY-MM-DD
* #param unix timestamp
* #return Returns a formated date (YYYY-MM-DD) or false
*/
function unixToIso8601($timestamp){
if($timestamp<0){return false;}//Do not accept negative values
/* Too many constants, add this to a class to speed things up. */
$year=1970;//Unix Epoc begins 1970-01-01
$dayInSeconds=86400;//60secs*60mins*24hours
$daysInYear=365;//Non Leap Year
$daysInLYear=$daysInYear+1;//Leap year
$days=(int)($timestamp/$dayInSeconds);//Days passed since UNIX Epoc
$tmpDays=$days+1;//If passed (timestamp < $dayInSeconds), it will return 0, so add 1
$monthsInDays=array();//Months will be in here ***Taken from the PHP source code***
$month=11;//This will be the returned MONTH NUMBER.
$day;//This will be the returned day number.
while($tmpDays>=$daysInYear){//Start adding years to 1970
$year++;
if(isLeap($year)){
$tmpDays-=$daysInLYear;
}
else{
$tmpDays-=$daysInYear;
}
}
if(isLeap($year)){//The year is a leap year
$tmpDays--;//Remove the extra day
$monthsInDays=array(-1,30,59,90,120,151,181,212,243,273,304,334);
}
else{
$monthsInDays=array(0,31,59,90,120,151,181,212,243,273,304,334);
}
while($month>0){
if($tmpDays>$monthsInDays[$month]){
break;//$month+1 is now the month number.
}
$month--;
}
$day=$tmpDays-$monthsInDays[$month];//Setup the date
$month++;//Increment by one to give the accurate month
return $year.'-'.(($month<10)?'0'.$month:$month).'-'.(($day<10)?'0'.$day:$day);
}
function isLeap($y){
return (($y)%4==0&&(($y)%100!=0||($y)%400==0));
}
echo unixToIso8601($t);
?>
You could convert to julian first with unixtojd() and then use cal_from_jd to split into year,month,day.
It's a little faster. The code below gives me this result:
2009-02-13 0.13018703460693 seconds using date()
2009-02-13 0.037487983703613 seconds using unixtojd(),cal_from_jd(),and sprintf()
function microtime_float(){
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
$unix_timestamp = 1234567890;
for($i=0;$i<10000;$i++) {
$d = date('Y-m-d',$unix_timestamp);
}
$time_stop = microtime_float();
echo $d . " " . ($time_stop - $time_start) . " seconds using date()<br>\n";
//////////////////////////
$time_start = microtime_float();
$unix_timestamp = 1234567890;
for($i=0;$i<10000;$i++) {
$julian_date = unixtojd($unix_timestamp);
$date_array = cal_from_jd($julian_date, CAL_GREGORIAN);
$d = sprintf('%d-%02d-%02d',$date_array['year'],$date_array['month'],$date_array['day']);
}
$time_stop = microtime_float();
echo $d . " " . ($time_stop - $time_start) . " seconds using unixtojd(),cal_from_jd(),and sprintf()<br>\n";

How to get millisecond between two dateTime obj?

How to get millisecond between two DateTime objects?
$date = new DateTime();
$date2 = new DateTime("1990-08-07 08:44");
I tried to follow the comment below, but I got an error.
$stime = new DateTime($startTime->format("d-m-Y H:i:s"));
$etime = new DateTime($endTime->format("d-m-Y H:i:s"));
$millisec = $etime->getTimestamp() - $stime->getTimestamp();`
I get the error
Call to undefined method DateTime::getTimestamp()
In the strict sense, you can't.
It's because the smallest unit of time for the DateTime class is a second.
If you need a measurement containing milliseconds then use microtime()
Edit:
On the other hand if you simply want to get the interval in milliseconds between two ISO-8601 datetimes then one possible solution would be
function millisecsBetween($dateOne, $dateTwo, $abs = true) {
$func = $abs ? 'abs' : 'intval';
return $func(strtotime($dateOne) - strtotime($dateTwo)) * 1000;
}
Beware that by default the above function returns absolute difference. If you want to know whether the first date is earlier or not then set the third argument to false.
// Outputs 60000
echo millisecsBetween("2010-10-26 20:30", "2010-10-26 20:31");
// Outputs -60000 indicating that the first argument is an earlier date
echo millisecsBetween("2010-10-26 20:30", "2010-10-26 20:31", false);
On systems where the size of time datatype is 32 bits, such as Windows7 or earlier, millisecsBetween is only good for dates between 1970-01-01 00:00:00 and 2038-01-19 03:14:07 (see Year 2038 problem).
Sorry to digg out an old question, but I've found a way to get the milliseconds timestamp out of a DateTime object:
function dateTimeToMilliseconds(\DateTime $dateTime)
{
$secs = $dateTime->getTimestamp(); // Gets the seconds
$millisecs = $secs*1000; // Converted to milliseconds
$millisecs += $dateTime->format("u")/1000; // Microseconds converted to seconds
return $millisecs;
}
It requires however that your DateTime object contains the microseconds (u in the format):
$date_str = "20:46:00.588";
$date = DateTime::createFromFormat("H:i:s.u", $date_str);
This is working only since PHP 5.2 hence the microseconds support to DateTime has been added then.
With this function, your code would become the following :
$date_str = "1990-08-07 20:46:00.588";
$date1 = DateTime::createFromFormat("Y-m-d H:i:s.u", $date_str);
$msNow = (int)microtime(true)*1000;
echo $msNow - dateTimeToMilliseconds($date1);
DateTime supports microseconds since 5.2.2. This is mentioned in the documentation for the date function, but bears repeating here. You can create a DateTime with fractional seconds and retrieve that value using the 'u' format string.
<?php
// Instantiate a DateTime with microseconds.
$d = new DateTime('2011-01-01T15:03:01.012345Z');
// Output the microseconds.
echo $d->format('u'); // 012345
// Output the date with microseconds.
echo $d->format('Y-m-d\TH:i:s.u'); // 2011-01-01T15:03:01.012345
// Unix Format
echo "<br>d2: ". $d->format('U.u');
function get_data_unix_ms($data){
$d = new DateTime($data);
$new_data = $d->format('U.u');
return $new_data;
}
function get_date_diff_ms($date1, $date2)
{
$d1 = new DateTime($date1);
$new_d1 = $d1->format('U.u');
$d2 = new DateTime($date2);
$new_d2 = $d2->format('U.u');
$diff = abs($new_d1 - $new_d2);
return $diff;
}
https://www.php.net/manual/en/class.datetime.php
Here's a function to do that + tests.
https://gist.github.com/vudaltsov/0bb623b9e2817d6ce359eb88cfbf229d
DateTime dates are only stored as whole seconds. If you still need the number of milliseconds between two DateTime dates, then you can use getTimestamp() to get each time in seconds (then get the difference and turn it into milliseconds):
$seconds_diff = $date2.getTimestamp() - $date.getTimestamp()
$milliseconds_diff = $seconds_diff * 1000

Categories