Reputation: 702
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.
Upvotes: 5
Views: 7920
Reputation: 702
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);
?>
Upvotes: 1
Reputation: 99909
Here is the function that date()
and DateTime::setTimestamp()
use to compute the date from a unix timestamp:
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
Upvotes: 6
Reputation: 1072
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";
Upvotes: 0