Microtime to Relative Date Conversion - php

I am receiving the following value from a database which is a millsecond (microtime) value
1369057622.4679
I would like to output this in PHP to be
3 Day's ago
Essentially reading the milliseconds value and converting it to a relative date string, can anyone suggest an easy method to do this.

You may do the following:
$input = 1369057622.4679;
$diff = floor(($input-time())/86400); // calculating the difference
$result = abs($diff) . (abs($diff)==1 ? ' day ':' days ') . ($diff<=0 ? 'ago':'ahead'); // making the result.
echo $result; // output: 1 day ago

Related

PHP count time and divide in daytime/nighttime

I have been trying to figure this out for a week now. My wife has started a new taxi-company and she asked me to code a simple webpage for here where she could press a button to save a timestamp, then the press is again when she gets off work, it then creates a second timestamp
I have an MYSQL database with rows containing the start time and stop time. I have managed to use the diff function to see how much time it is between the two timestamps but now comes the tricky part.
Since it's different payments at different times of the day I need to divide the time at a shortened time.
Up to 19:00 she works "daytime" and after that, she works "nighttime" until 06:00 the other day, then there is "weekend daytime" and "weekend nighttime" as well.
So if she creates a timestamp whit the date and time: 2018-08-08 06:30 and then another timestamp at 2018-08-08 21:00, then I need a script that puts these data in ex "$daytimehours = 12" "$daytimeminutes = 30" and "$nighttimehours = 3" "$nighttimeminutes = 0"
I have managed to create a script that almost works, but it is several pages long, and it contains one if-statement for each different scenario daytime-nighttime, nighttime-daytime etc.
So do anyone has a good idea on how to solve this? or maybe just point me in the right direction. I would be happy to pay some money to get this to work.
My solution is
<?php
date_default_timezone_set('Asia/Almaty');
$endDate = '2018-08-08 21:00';
$startDate = '2018-08-08 06:30';
$nightmare = date('Y-m-d 19:00');
$startDay = date('Y-m-d 06:00');
$diffMorning = strtotime($nightmare) - strtotime($startDate);
$diffNight = strtotime($endDate) - strtotime($nightmare);
echo gmdate('H:i', $diffMorning) . "\n"; // this is the difference from start day till 19:00
echo gmdate('H:i', $diffNight); // this is the difference on nightmare
$total = $diffMorning + $diffNight;
echo intval($total/3600) . " hours \n";
echo $total%3600/60 . " minutes \n";
echo $total%3600%60 . ' seconds';
You can check via online compiler
given two dates stated as:
$endDate = '2018-08-08 21:00';
$startDate = '2018-08-08 06:30';
you can use the PHP Date extension to achieve the difference like this:
$start = date_create($startDate);
$end = date_create($endDate);
$boundnight = clone($end);
$boundnight->setTime(19,00);
$total_duration = date_diff($end,$start);//total duration from start to end
$day_duration = date_diff($boundnight,$start);//daytime duration
$night_duration = date_diff($end,$boundnight);// nighttime duration
you can use the format method to print a human readable string this way:
$total_duration=$total_duration->format('%H:%I');
$day_duration=$day_duration->format('%H:%I');
$night_duration=$night_duration->format('%H:%I');
At this step there is nothing left but you say you want to convert each duration in minutes.So let's build a function :
function toMinute($duration){
return (count($x=explode(':',$duration))==2?($x[0]*60+$x[1]):false);
}
Then you can use it this way:
$total_duration = toMinute($total_duration);
$day_duration = toMinute($day_duration);
$night_duration = toMinute($night_duration);
The output of
var_dump($total_duration,$day_duration,$night_duration) at this step is:
int(870)
int(750)
int(120)

calculating what second of the day an event occurred

I made some code that works, but it seems very inefficient. I am charting circles on a canvas to show when events happen during a work day. To do this I find the number of seconds of the day this happened, then convert this to minutes to show.
My question is why do I have to go strtotime(date('...',strtotime(time))) and call strtotime twice?
When I just had it like strtotime(date('Y-m-d',time) I would get a negative value.
<?php
$time_concerned = '2014-10-31 02:00:00';
$start_day_temp = strtotime(date('Y-m-d',strtotime($time_concerned)));
$end_day_temp = strtotime(date('Y-m-d H:i',strtotime($time_concerned)));
$num_seconds = $end_day_temp - $start_day_temp;
//divide by 60 to get minutes. divide in half to make fit on 720 scale.
$num_conv_minutes = (($num_seconds/60)/2);
echo ' ctx.fillStyle = "#00FF00";';
echo ' ctx.beginPath();';
echo ' ctx.arc('.$num_conv_minutes.'+ x_inbound,y_truck_arrivals,5,0,2*Math.PI);';
echo ' ctx.fill();';
echo ' ctx.stroke();';
?>
$time_concerned = '2014-10-31 02:00:00';
echo strtotime(date('Y-m-d',strtotime($time_concerned)));
echo "\r\n";
echo strtotime($time_concerned);
Try this. Fiddle.
These are almost the same thing. The only reason they're different is because when you convert the string to a date you're dropping the second minutes and hours, so PHP puts it to midnight and you lose the part that tells you you did all this at 2am.
This is useful the first time you use it because you need to get the timestamp of midnight to subtract from the other timestamp. However, the second time it's just redundant.
So here's how you do it..
$time_concerned = '2014-10-31 02:00:00';
$start_day_temp = strtotime(date('Y-m-d',strtotime($time_concerned)));
$end_day_temp = strtotime($time_concerned);

PHP - Split ugly date string and then do date maths on it?

I'm a PHP beginner and been struggling unsuccessfully with the php documentation. Seems a lot of ways to do what I want.
Basically I need a php page to check an "ugly" date/time variable appended to a URL - it must convert it into a usable format and subtract it from the current date/time. If the result is less than 48hrs then the page should redirect to "Page A" otherwise it should redirect to "Page B"
This is what the URL and variable looks like.
http://mysite.com/special-offer.php?date=20130527212930
The $date variable is the YEAR,MONTH,DAY,HOUR,MINUTE,SECOND. I can't change the format of this variable.
I'm guessing PHP can't use that string as it is. So I need to split it somehow into a date format PHP can use. Then subtract that from the current server date/time.
Then put the result into an if/else depending on whether the result is more or less than 48hrs.
Am I right in theory? Can anyone help me with the "practise"?
Thanks!
Take a look at the DateTime class and specifically the createFromFormat method (php 5.3+):
$date = DateTime::createFromFormat('YmdHis', '20130527212930');
echo $date->format('Y-m-d');
You might need to adjust the format depending on the use of leading zeros.
PHP 5 >= 5.3.0
$uglydate = '20130527212930';
// change ugly date to date object
$date_object = DateTime::createFromFormat('YmdHis', $uglydate);
// add 48h
$date_object->modify('+48 hours');
// current date
$now = new DateTime();
// compare dates
if( $date_object < $now ) {
echo "It was more than 48h ago";
}
You can use a regular expression to read your string and construct a meaningful value.
for example
$uglydate = "20130527212930";
preg_match("/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/", $uglydate, $matches);
$datetime = $matches[1] . "-" . $matches[2] . "-" . $matches[3] . " " . $matches[4] . ":" . $matches[5] . ":" . $matches[6];
//then u can use $datetime in functions like strtotime etc
Whoa! you all have WAY too much time on your hands... Nice answers... oh well, i'll pop-in a complete solution...
<?php
$golive = true;
if (preg_match('|^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})|', $_GET['date'], $matches)) {
list($whole, $year, $month, $day, $hour, $minute, $second) = $matches;
// php: mktime function (using parameters derived
$timestamp = mktime($hour,$minute,$second,$month,$day,$year);
$diff = time()-$timestamp;
$diffInHours = $diff / 3600 ;
// if less, than 48
if ( $diffInHours < 48 ) {
$location = "http://bing.com";
} else {
$location = "http://google.com";
}
//
if ( $golive ) {
header("Location: ".$location);
exit();
} else {
echo "<p>You are would be sending the customer to:<br><strong>$location</strong>";
}
} else {
echo "<p>We're not sure how you got here, but... 'Welcome!'???</p>";
}
That oughta do it.
By the way, on another note, I'd heavily suggest you go back to the sending party of that URL and definitely reconsider how this is being done. As this is VERY easily tweakable (URL date= value), thus not really protecting anything, but merely putting the keys on the front porch next to the 'Guardian Alarms Installed at This House' {sign} :).
Assuming the input is in the correct format (correct number of characters and all of them digits) you'll need 1 substring of length 4 and the rest of lenght 2. For simplicity I'll ignore the first 2 chars (the 20 part from 2013) with substr
$input=substr($input, 2, strlen($input));
Now I can treat all the remaining elements in the string as 2-char pairs:
$mydate=array(); //I'll store everything in here
for($i=0; $i<=strlen($input)-2; $i+=2){
$mydate[$a]=substr($input, $i, $i+2);
$a++;
}
Now I have year, month, day etc. in an array indexed from 0 to 5. For the date difference I'll put the array into mktime:
$timestamp = mktime(mydate[3], mydate[4], mydate[5], mydate[1], mydate[2], mydate[0]);
Finally compare the two timestamps:
if($old_ts - $timestamp > (60*60*48)){
//more than 48 hours
}else{ ... }

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";

Parse and create ISO 8601 Date and time intervals, like PT15M in PHP

A library and webservice I am using communicates time-intervals in ISO 8601 format: PnYnMnDTnHnMnS. I want to convert such formats to seconds. And vice versa. Seconds are a lot easier to calculate with.
Example interval values are:
PT1M or PT60S (1 minute)
PT1H, PT60M or PT3600S (1 hour)
I need two functions: parse from such values to seconds: iso8601_interval_to_seconds() and from seconds into such intervals: iso8601_interval_from_seconds().
The latter is rather simple, because it could be done as `"PT{$seconds}S", just pass seconds along, at all times. Maybe this can be done nicer with a parser that switches to H(hour) or M(minute)?
The first is harder, but maybe there is a trick with one of the many string-to-date converters in PHP? I would love to learn how to use such a function for parsing intervals. Or learn an alternative.
It looks like PHP 5.3's DateInterval supports this.
If you can't use 5.3, I suppose any such conversion function would know how many seconds are in a year, a month, a day, an hour, and a minute. Then, when converting from seconds, it would divide in that order, each time taking the modulo of the previous operation, until only <60 seconds are left. When converting from an ISO 8601 interval representation it should be trivial to parse the string and multiply each found element accordingly.
strtotime won't work with the ISO 8601 format directly (eg. P1Y1DT1S),
but the format that it does understand (1Year1Day1Second) is not too
far off -- it would a pretty straight-forward conversion. (a little
"hacky"... but that's PHP for you).
Thanks Lee, I was not aware strtotime accepted this format. This was the missing part of my puzzle. Perhaps my functions can complete your answer.
function parse_duration($iso_duration, $allow_negative = true){
// Parse duration parts
$matches = array();
preg_match('/^(-|)?P([0-9]+Y|)?([0-9]+M|)?([0-9]+D|)?T?([0-9]+H|)?([0-9]+M|)?([0-9]+S|)?$/', $iso_duration, $matches);
if(!empty($matches)){
// Strip all but digits and -
foreach($matches as &$match){
$match = preg_replace('/((?!([0-9]|-)).)*/', '', $match);
}
// Fetch min/plus symbol
$result['symbol'] = ($matches[1] == '-') ? $matches[1] : '+'; // May be needed for actions outside this function.
// Fetch duration parts
$m = ($allow_negative) ? $matches[1] : '';
$result['year'] = intval($m.$matches[2]);
$result['month'] = intval($m.$matches[3]);
$result['day'] = intval($m.$matches[4]);
$result['hour'] = intval($m.$matches[5]);
$result['minute'] = intval($m.$matches[6]);
$result['second'] = intval($m.$matches[7]);
return $result;
}
else{
return false;
}
}
The function also supports negative formats.
-P10Y9MT7M5S will return an array like:
[year] => -10 [month] => -9 [day] => 0 [hour] => 0 [minute] => -7 [second] => -5 If this behaviour is not desired pass false as second parameter. This way the function will always return positive values. The min/plus symbol will still be available in result key ['symbol'].
And a little update:
This function uses the first function to get the total amount of seconds.
function get_duration_seconds($iso_duration){
// Get duration parts
$duration = parse_duration($iso_duration, false);
if($duration){
extract($duration);
$dparam = $symbol; // plus/min symbol
$dparam .= (!empty($year)) ? $year . 'Year' : '';
$dparam .= (!empty($month)) ? $month . 'Month' : '';
$dparam .= (!empty($day)) ? $day . 'Day' : '';
$dparam .= (!empty($hour)) ? $hour . 'Hour' : '';
$dparam .= (!empty($minute)) ? $minute . 'Minute' : '';
$dparam .= (!empty($second)) ? $second . 'Second' : '';
$date = '19700101UTC';
return strtotime($date.$dparam) - strtotime($date);
}
else{
// Not a valid iso duration
return false;
}
}
$foo = '-P1DT1S';
echo get_duration_seconds($foo); // Output -86399
$bar = 'P1DT1S';
echo get_duration_seconds($bar); // Output 86401
Be aware that converting durations that contain Days, Months, and/or Years into a duration like seconds can not be done accurately without knowing an actual starting date/time.
For Example
1 SEP 2010: +P1M2D means +2764800 seconds
1 OCT 2010: +P1M2D means +2851200 seconds
That's because September has 30-days, and October has 31-days. The same problem occurs with converting Year intervals, because of leap-years and leap-seconds. Leap-years introduce further complexity to the Month conversion as well - since February is one day longer in leap-years than it is otherwise. Days are problematic in areas where daylight saving time is practiced - a one-day period occurring during the DST transition, is actually 1-hour longer than it would be otherwise.
All that being said -- you can, of course, compress values containing only Hours, Minutes, and Seconds into values containing just Seconds. I'd suggest that you build a simple parser to do the job (or maybe consider a regular expression).
Just be aware of the pitfalls outlined above -- there there be dragons. If you intend to deal with Days, Months, and/or Years, you need to use one of the built-in mechanisms to do the math for you in the context of a known date/time. As others have mentioned: the DateInterval class, in combination withe the functions provided on the DateTime class is probably the most intuitive way to deal with this. But that's only available in PHP version 5.3.0 or greater.
If you have to work with less than v5.3.0, you can try to build something around this little gem:
$startDateTime = '19700101UTC';
$duration = strtotime( $startDateTime.'+1Year1Day1Second' ) - strtotime($startDateTime);
print("Duration in Seconds: $duration");
strtotime won't work with the ISO 8601 format directly (eg. P1Y1DT1S), but the format that it does understand (1Year1Day1Second) is not too far off -- it would a pretty straight-forward conversion. (a little "hacky"... but that's PHP for you).
good luck!
function parsePTTime($pt_time)
{
$string = str_replace('PT', '', $pt_time);
$string = str_replace('H', 'Hour', $string);
$string = str_replace('M', 'Minute', $string);
$string = str_replace('S', 'Second', $string);
$startDateTime = '19700101UTC';
$seconds = strtotime($startDateTime . '+' . $string) - strtotime($startDateTime);
return $seconds;
}
Tests:
PT1H - OK
PT23M - OK
PT45S - OK
PT1H23M - OK
PT1H45S - OK
PT23M45S - OK
PT1H23M45S - OK
What you are looking for is DateTime::diff
The DateInterval object representing the difference between the two dates or FALSE on failure as illustrated below:
$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%d days');
Just use seconds instead of dates.
This is from http://www.php.net/manual/en/datetime.diff.php
For a reference to DateInterval see http://www.php.net/manual/en/class.dateinterval.php

Categories