PHP date() to Excel serial format conversion - php

I've looked for hours now. Everywhere I see examples of how to convert the Excel serial date number to UNIX_Date.
What I want to do is a PHP date("Y-m-d H:i:s") to convert it to Excel serial date number.
Example:
$php_date = date("Y-m-d H:i:s"); // "2019-04-18 11:57:25" at the time
and if I type this "2019-04-18 11:57:25" in Excel cell, and format it to show a number then Excel shows me "43573.4982060185"
How to get this "43573.4982060185" in PHP?
EDIT:
As per Morgan's answer bellow I have a function now that does this:
EDIT 2:
Added timezone set to get my local time, if anyone else needs this, set for your local timezone. List of supported timezones for PHP can be found here https://www.php.net/manual/en/timezones.php
function PHP_to_Excel() {
date_default_timezone_set("Europe/London");
$datetime = date("Y-m-d H:i:s");
$strdate = strtotime($datetime);
$excel_date = floatval(25569 + ($strdate / 86400));
return $excel_date;
}
The above function will return the correct serial number for the current local date and time.

Here:
<?php
date_default_timezone_set('America/New_York');
$date_time = date("Y-m-d H:i:s");
$str_date = strtotime($date_time . ' +1 day');
$excel_date = floatval(25569 + $str_date / 86400);
var_dump($excel_date);
You should change time zone with your current, you can see all timezones here
Return:
float(43573.46537037)

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

PHP : How to convert a Windows FILETIME String from LDAP into a readable DATE? [duplicate]

This question already has answers here:
Convert Windows Timestamp to date using PHP on a Linux Box
(2 answers)
Closed 2 years ago.
I'm querying MS LDAP and some date fields about user have this kind of value : 132497313049180481.
It seems to be in the Windows FILETIME format that is use for some informations in LDAP and Active Directory as a timestamp.
How to convert it into a readable DATE ?
This convert Windows FILETIME (ex: 132497313049180481) to a human readable datetime (in this case: "2020-11-13 08:55:04").
I hope it can be usefull :
$filetime = "132497313049180481";
echo filetimeToStr($filetime); // Will display "2020-11-13 08:55:04"
function filetimeToStr($filetime){
date_default_timezone_set ("UTC"); //For a result not depending on server time zone.
$resp = (int)($filetime / 10000000); //Number of seconds since 1601-01-01.
$diff = 11644473600; //Number of seconds between FILETIME & Unix timestamp.
$resp = $resp - $diff; //Actual Unix timestamp matching your filetime.
$resp = date("Y-m-d H:i:s", $resp);
return $resp;
}
Wanna know where the 11644473600 come from ?
MSDN say that FILETIME :
Contains a 64-bit value representing the number of 100-nanosecond
intervals since January 1, 1601 (UTC). https://learn.microsoft.com/fr-be/windows/win32/api/minwinbase/ns-minwinbase-filetime?redirectedfrom=MSDN
About Unix timestamp :
Unix epoch is the time 00:00:00 UTC on 1 January 1970 ... every day is
treated as if it contains exactly 86400 seconds.
https://en.wikipedia.org/wiki/Unix_time
date_default_timezone_set ("UTC"); //For a result not depending on server time zone.
$start_date = date_create("1601-01-01");
$end_date = date_create("1970-01-01");
$diff = date_diff($start_date, $end_date);
$diff = (int)$diff->format("%a"); //Number of days between FILETIME & Unix timestamp
$diff = ($diff * 86400); //Number of seconds between FILETIME & Unix timestamp
echo $diff; //Will display 11644473600
EDITED
Added date_default_timezone_set ("UTC"); for a result not depending on server time zone (Thanks #jspit).
The createDateTimeFromSystemTime() function returns a DateTime object. It can be used universally and also works under 32-bit systems. With other parameters for $basis and $resolution, this function can also process other time stamps (LabVIEW Timestamp, Mac Timestamp ..)
function createDateTimeFromSystemTime(
$time, //num.String, integer or float
$basis = '1601-1-1',
$resolution = 1.E-7,
$timeZone = 'UTC'
){
return date_create($basis.' UTC')
->modify(round($time * $resolution).' Seconds')
->setTimeZone(new DateTimeZone($timeZone));
}
How to use for LDAP-Timestamp:
$ldapTimestamp = "132497313049180481";
$dateTime = createDateTimeFromSystemTime($ldapTimestamp);
echo $dateTime->format('Y-m-d H:i:s T');
//2020-11-13 08:55:05 UTC
The algorithm is from this class.

Read date value from import Excel in PHP

I've problem with read date value from import value (Excel) to mysql database. i've code as below :
$dataexcel[$i-3]['date_edit'] = date('m/d/Y', strtotime(trim($data['cells'][$i][25])));
i tried use strtotimeto define value from excel, but i've problem to save it into database, if my value in excel with excel date format is 1/1/2018 (it read as 1 Jan 2018, English time format), after i used my code above, it saved become 1970-01-01 it means 1 Jan 1970.
in another example,
i tried another input with date 2/1/2018, it saved into database as 2018-02-02.
from my samples above, in first there missmatch problem with year, then and in the 2nd sample missmatch problem come from date,
so how to declare date to solve my problem, if i want to save date format with simple way?
if there any advice , please, thanks...
From your comment answer, you can modification some code like below :
$date = str_replace("/", ".", $data['cells'][$i][25]);
$dates = date("Y-m-j", strtotime($date));
$dataexcel[$i-3]['date_edit'] = $dates;
$date still pick up from value without used strotime, so date format didn't read correctly...
You can convert the excel date to mysql date like below I did.
//Your input date
$input_date = $sheet->getCellByColumnAndRow(1,$i)->getValue();
$excel_date = $input_date; //here is that excel value 41621 or 41631
//Convert excel date to mysql db date
$unix_date = ($excel_date - 25569) * 86400;
$excel_date = 25569 + ($unix_date / 86400);
$unix_date = ($excel_date - 25569) * 86400;
//echo gmdate("Y-m-d", $unix_date);
//Insert below to sql
$added_date = gmdate("Y-m-d", $unix_date);
A simple function will do this thing
$date = str_replace("/", ".", $data['cells'][$i][25]);// replace the / with .
$date = date("Y-m-d", strtotime($date));
$dataexcel[$i-3]['date_edit'] = $date;
And in the database the default date format is YYYY-MM-DD , so it save correctly to the db
keep it simple. use a defined dateformat when reading the file (the dateformat can be provided as a parameter in case it needs to be adjustable). then, read the date in the following way instead of just using strtotime (taken from php.net's example):
$date = DateTime::createFromFormat('j-M-Y', '15-Feb-2009');
relevant example to your code, using the previous $date var:
$dataexcel[$i-3]['date_edit'] = $date->format("y-M-Y");
more info - http://php.net/manual/en/datetime.createfromformat.php

PHP, date is offset by 1 day. Going from DOY (Y-z) format to string/unix

I'm required to take a date in the format 'Y-z' which is year-doy (e.g, 2013-146) and convert that into a unix time stamp to be store into a database.
The issue i have is that i input 2013-146 and turn it into a DateTime Object. then when i output this date in unix or 'Y-m-d' format i get 2013-5-27 not 2013-5-26 which is the correct day.
You can verify the DOY on this NASA website and this NOAA website.
Summary:
--I have the date: '2013-146'
--Using DateTime::createFromFormat and echoing using 'Y-m-d' and 'Y-z' i get: 2013-5-27 and 2013-146 respectively.
--This does not agree with the NASA website I listed and is offset by one day can anyone verify that I'm not losing my mind?
Here is the code you can test:
<?php
date_default_timezone_set('America/Chicago');
$year = 2013; //where this outputs a simple year 'CCYY'
$day = 146; //where this provides the day of year
$format = 'Y-z'; //specifying what format i'm creating the datetime with
$date = $year.'-'.$day; //formatting the strings to the above $format
$timezone = new DateTimeZone('America/Chicago'); //specify the timezone
$fileDateStore = DateTime::createFromFormat($format, $date, $timezone);//, $timezone); //create the DateTime object
$fileDateString = date_format($fileDateStore,"Y-m-d"); //format it so strtotime() can read it
$fileDate = strtotime($fileDateString); //finally create the Unix Timestamp for the date.
$newfileDOY = date_format($fileDateStore,"Y-z");
echo 'newfileDOY = '.$newfileDOY.', ';
echo 'date = '.$date.', ';
echo 'fileDateString = '.$fileDateString.', ';
echo 'fileDate = '.$fileDate.PHP_EOL;
?>
The problem is than z format in PHP begins with 0 and not with 1.
Look at: http://www.php.net/manual/en/function.date.php
z: The day of the year (starting from 0)

In an LDAP 'lastlogon' lookup how do I decipher the result?

I'm using a PHP script to grab data from Active Directory using LDAP..
When I get the user values for 'lastlogon' I get a number like 129937382382715990
I've tried to figure out how to get the date/time from this but have no idea, can anybody help?
Read this comment on the PHP: LDAP Functions page.
All of them are using "Interval" date/time format with a value that represents the number of 100-nanosecond intervals since January 1, 1601 (UTC, and a value of 0 or 0x7FFFFFFFFFFFFFFF, 9223372036854775807, indicates that the account never expires): https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
So if you need to translate it from/to UNIX timestamp you can easily calculate the difference with:
<?php
$datetime1 = new DateTime('1601-01-01');
$datetime2 = new DateTime('1970-01-01');
$interval = $datetime1->diff($datetime2);
echo ($interval->days * 24 * 60 * 60) . " seconds\n";
?>
The difference between both dates is 11644473600 seconds. Don't rely on floating point calculations nor other numbers that probably were calculated badly (including time zone or something similar).
Now you can convert from LDAP field:
<?php
$lastlogon = $info[$i]['lastlogon'][0];
// divide by 10.000.000 to get seconds from 100-nanosecond intervals
$winInterval = round($lastlogon / 10000000);
// substract seconds from 1601-01-01 -> 1970-01-01
$unixTimestamp = ($winInterval - 11644473600);
// show date/time in local time zone
echo date("Y-m-d H:i:s", $unixTimestamp) ."\n";
?>
This is the number 100-nanosecond ticks since 1 January 1601 00:00:00 UT.
System time article in Wikipedia can give you more details.
What about this:
$timeStamp = 129937382382715990;
echo date('Y-m-d H:i:s', $timeStamp);
EDIT ------
I just tried the following and noticed that this method wont work unless the clock on your machine is set 10 years in the future. Below is the code I used to prove the above pretty much useless unless you do more processing maybe..
$time = time();
echo date('Y-m-d H:i:s', $time);
echo "<br />";
$timeStamp = 129937382382715990;
echo date('Y-m-d H:i:s', $timeStamp);
In my case I'm using Pentaho. With a Modified Javascript value you can convert the values, lastLogon is the column I wanna convert from data stream:
calendar = java.util.Calendar.getInstance();
calendar.setTime(new Date("1/1/1601"));
base_1601_time = calendar.getTimeInMillis();
calendar.setTime(new Date("1/1/1970"));
base_1970_time = calendar.getTimeInMillis();
ms_offset = base_1970_time - base_1601_time;
calendar.setTimeInMillis( lastLogon / 10000 - ms_offset); //lastLogon is a column from stream
var converted_AD_time = calendar.getTime(); // now just add this variable 'converted_AD_time' to the 'Fields' as a show in the image below

Categories