I have here a mysql query that get the average of the column(the column data type is 'time'). The column values for example are:
00:00:55, 00:00:59, 00:01:03
SELECT AVG(TIME_TO_SEC(column_name)) FROM table_name)AS average_result
In my Php I formatted the result this way:
<?php foreach($display_average as $da){
echo date("H:i:s", ($da["average_result"]));
}
?>
Outputs: 08:00:59 instead of 00:00:59, Why does this starts with 08? Or did I miss something? Thanks!
Both PHP's date/time functions and MySQL's date/time data types handle wall clock timestamps, not durations; i.e. 00:00:55 means fifty-five seconds past midnight. This is not what you want; you couldn't handle durations longer than 23 hours, 59 minutes, 59 seconds, because the data types and functions you're using are handling clock time, which cannot exceed these values.
Your specific issue stems from timezone settings. Your larger issue is that you need to store simple integer values expressing elapsed seconds or minutes; not timestamps. To format that into a human readable string in PHP you can use the DateInterval class.
see php manul, about the date_default_timezone_set your timezone is +8
the default date.timezone of PHP is utc, u can change it to date.timezone = PRC
date_default_timezone_set('UTC');
echo date("H:i:s", 59);//00:00:59
//date_default_timezone_set('RPC');
//echo date("H:i:s", 59);//08:00:59
Always go for standard/formal approaches. But if anyhow you need it custom, then you can do almost everything with programming. Here we go
Get your time as numbers (number of seconds in your time filed) from database as
SELECT
AVG
(
HOUR(column_name) * 3600
+ MINUTE(column_name) * 60
+ SECOND(column_name)
) AS numeric_average_result FROM table_name
Now you can convert number of seconds to proper time as
foreach($display_average as $da)
{
$r = numToTime($da["numeric_average_result"]);
echo "<br>".$r;
}
function numToTime($num)
{
$seconds = $num%60;
$num = (int)($num/60);
$minutes = $num%60;
$hours = (int)($num/60);
return make2digit($hours).":".make2digit($minutes).":".make2digit($seconds);
}
function make2digit($val)
{
if(strlen($val) == 1)
return "0".$val;
else
return $val;
}
Related
This is a two part problem which should be trivial but date and time handling in PHP seems to be anything but and everything I've tried so far has either given incorrect results or crashed my program
I'm trying to replicate the following two SQL Server commands in PHP
Count the days since the start of the millennium
select (cast (DATEDIFF(day,'2000-01-01',getdate()) as int)
Count the number of seconds since midnight
datediff(second,convert(date,getdate()),getdate())
I've tried all combinations of date_diff, getdate, strotime and more but nothing seems to give me a properly ISO formatted datetime or a workable method of calculating days and seconds elapsed.
I'm using PHP7 so should have all built-in functions up to date.
What am I missing?
edit: sample input data.
today's date in format '2020-11-22 16:57:10.112'
a given date in format '2000-01-01 00:00:00.000'
expected output data : 7631 days
today's date in format '2020-11-22 16:57:10.112'
previous midnight in format '2020-11-22 00:00:00.000'
expected output data : 61215 seconds
It's rather easy to do if you know your way around DateTime:
function daysSinceStartOfMillennium(DateTimeImmutable $date): int
{
$millenniumStart = new DateTimeImmutable('2000-01-01');
return $date->diff($millenniumStart)->days;
}
function secondsSinceMidnightOfDate(DateTimeImmutable $date): int
{
$midnightToday = new DateTimeImmutable('today');
$diff = $date->diff($midnightToday);
return $diff->s // seconds
+ $diff->i * 60 // minutes to seconds
+ $diff->h * 60 * 60 // hours to seconds
;
}
You could also modify the functions to take date strings as arguments and create a DateTime object inside them.
I opted to create a descriptive variable inside the millennium function to better convey the solution. The creation of this variable can be omitted if you wish and the argument passed directly into the return statement:
return $date->diff(new DateTimeImmutable('2000-01-01'))->days;
Note that if you only need to use these function for the current date, they can be simplified to take no arguments:
function daysSinceStartOfMillennium(): int
{
$millenniumStart = new DateTimeImmutable('2000-01-01');
return (new DateTimeImmutable())->diff($millenniumStart)->days;
}
function secondsSinceMidnight(): int
{
$midnightToday = new DateTimeImmutable('today');
$diff = (new DateTimeImmutable())->diff($midnightToday);
return $diff->s // seconds
+ $diff->i * 60 // minutes to seconds
+ $diff->h * 60 * 60 // hours to seconds
;
}
I would like to display a length of time measured in hours, minutes and seconds where some lengths of time are greater than 24 hours. Currently I am trying this:
$timeLength = new DateTime();
$timeLength->setTime(25, 30);
echo $timeLength->format('H:m:i'); // 01:30:00
I would like it to display 25:30:00.
I am looking preferably for an object oriented solution.
Thanks :)
Since you already have the length in seconds, you can just calculate it:
function timeLength($sec)
{
$s=$sec % 60;
$m=(($sec-$s) / 60) % 60;
$h=floor($sec / 3600);
return $h.":".substr("0".$m,-2).":".substr("0".$s,-2);
}
echo timeLength(6534293); //outputs "1815:04:53"
If you really want to use DateTime object, here's a (kind of cheating) solution:
function dtLength($sec)
{
$t=new DateTime("#".$sec);
$r=new DateTime("#0");
$i=$t->diff($r);
$h=intval($i->format("%a"))*24+intval($i->format("%H"));
return $h.":".$i->format("%I:%S");
}
echo dtLength(6534293); //outputs "1815:04:53" too
If you need it OO and don't mind creating your own class, you can try
class DTInterval
{
private $sec=0;
function __construct($s){$this->sec=$sec;}
function formet($format)
{
/*$h=...,$m=...,$s=...*/
$rst=str_replace("H",$h,$format);/*etc.etc.*/
return $rst;
}
}
DateTime handles time-of-day, not time intervals. And since there's no 25 o'clock, it's the wrong thing to use. There's DateInterval though, which handles date intervals. Use it or do some manual calculation. Even with DateInterval though you'll have to do some calculations, since it'll break down an interval into days and hours. The most straight forward thing to do is to calculate what you need based on the seconds you already have.
I'm being told that this below method of calculating the user's local time is sometimes not working. What's the best way to do this in PHP? What do you do?
public function getTimeOffset ($time) {
$this->_cacheTimeOffset();
if ($this->timeOffsetExecuted) {
$d = date("O");
$neg = 1;
if (substr($d, 0, 1) == "-") {
$neg = -1;
$d = substr($d, 1);
}
$h = substr($d, 0, 2)*3600;
$m = substr($d, 2)*60;
return $time + ($neg * ($h + $m) * -1) + (($this->timeOffset + $this->getDstInUse()) * 3600);
}
return $time;
}
Use the DateTime extension, such as DateTime::getOffset,
or DateTimeZone::getOffset
Some countries might have perform several timezone update,
this method DateTimeZone::getTransitions reveal the transition history
Just answered a very similar question over here. I recommend you check that one out; I explained the two preferred ways of doing timezone offset calculation (using simple math, and then the datetimezone and datetime classes) pretty thoroughly.
The first way would be the easiest
(and most logical) way, and that is to
store their offset (if you already
have it, that is) and multiply that by
3600 (1 hour in seconds), and then add
that value to the current unix timestamp to get their final time of
running.
Another way to do it is to use the
DateTime and DateTimeZone classes.
How these two classes work, as shown
here, is that you create two
DateTimeZone objects, one with your
timezone and one with theirs; create
two DateTime objects with the first
parameters being "now" and the
second being the reference to the
DateTimeZone objects above
(respectively); and then call the
getOffset method on your timezone
object passing their timezone object
as the first parameter, ultimately
getting you the offset in seconds that
can be added to the current unix
timestamp to get the time that their
job needs to run.
date('Z');
returns the UTC offset in seconds.
A quick solution:
<?php echo date('g:i a', strtotime("now + 10 hours 30 minutes")); ?>
I have two times in PHP and I would like to determine the elapsed hours and minutes. For instance:
8:30 to 10:00 would be 1:30
A solution might be to use strtotime to convert your dates/times to timestamps :
$first_str = '8:30';
$first_ts = strtotime($first_str);
$second_str = '10:00';
$second_ts = strtotime($second_str);
And, then, do the difference :
$difference_seconds = abs($second_ts - $first_ts);
And get the result in minutes or hours :
$difference_minutes = $difference_seconds / 60;
$difference_hours = $difference_minutes / 60;
var_dump($difference_minutes, $difference_hours);
You'll get :
int 90
float 1.5
What you now have to find out is how to display that ;-)
(edit after thinking a bit more)
A possibility to display the difference might be using the date function ; something like this should do :
date_default_timezone_set('UTC');
$date = date('H:i', $difference_seconds);
var_dump($date);
And I'm getting :
string '01:30' (length=5)
Note that, on my system, I had to use date_default_timezone_set to set the timezone to UTC -- else, I was getting "02:30", instead of "01:30" -- probably because I'm in France, and FR is the locale of my system...
You can use the answer to this question to convert your times to integer values, then do the subtraction. From there you'll want to convert that result to units-hours-minutes, but that shouldn't be too hard.
Use php timestamp for the job :
echo date("H:i:s", ($end_timestamp - $start_timestamp));
$d1=date_create()->setTime(8, 30);
$d2=date_create()->setTime(10, 00);
echo $d1->diff($d2)->format("%H:%i:%s");
The above uses the new(ish) DateTime and DateInterval classes. The major advantages of these classes are that dates outside the Unix epoch are no longer a problem and daylight savings time, leap years and various other time oddities are handled.
$time1='08:30';
$time2='10:00';
list($h1,$m1) = explode(':', $time1);
list($h2,$m2) = explode(':', $time2);
$time_diff = abs(($h1*60+$m1)-($h2*60+$m2));
$time_diff = floor($time_diff/60).':'.floor($time_diff%60);
echo $time_diff;
In Actionscript, the Unix timestamp in milliseconds is obtainable like this:
public static function getTimeStamp():uint
{
var now:Date = new Date();
return now.getTime();
}
The doc clearly states the following:
getTime():Number Returns the number of
milliseconds since midnight January 1,
1970, universal time, for a Date
object.
When I trace it, it returns the following:
824655597
So, 824655597 / 1000 / 60 / 60 / 24 / 365 = 0.02 years.
This is obviously not correct, as it should be around 39 years.
Question #1: What's wrong here?
Now, onto the PHP part: I'm trying to get the timestamp in milliseconds there as well. The microtime() function returns either a string (0.29207800 1246365903) or a float (1246365134.01), depending on the given argument. Because I thought timestamps were easy, I was going to do this myself. But now that I have tried and noticed this float, and combine that with my problems in Actionscript I really have no clue.
Question #2: how should I make it returns the amount of milliseconds in a Unix timestamp?
Timestamps should be so easy, I'm probably missing something.. sorry about that. Thanks in advance.
EDIT1: Answered the first question by myself. See below.
EDIT2: Answered second question by myself as well. See below. Can't accept answer within 48 hours.
I used unsigned integer as the return type of the function. This should be Number.
public static function getTimeStamp():Number
{
var now:Date = new Date();
return now.getTime();
}
Think I got the function for getting milliseconds in PHP5 now.
function msTimeStamp() {
return round(microtime(1) * 1000);
}
For actionscript3, new Date().getTime() should work.
In PHP you can simply call time() to get the time passed since January 1 1970 00:00:00 GMT in seconds. If you want milliseconds just do (time()*1000).
If you use microtime() multiply the second part with 1000 to get milliseconds. Multiply the first part with 1000 to get the milliseconds and round that. Then add the two numbers together. Voilá.
Use this:
intval(microtime(true)*1000)
To normalize a timestamp as an integer with milliseconds between Javascript, Actionscript, and PHP
Javascript / Actionscript:
function getTimestamp(){
var d = new Date();
return Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()).valueOf();
}
PHP:
function getTimestamp(){
$seconds = microtime(true); // true = float, false = weirdo "0.2342 123456" format
return round( ($seconds * 1000) );
}
See PHP note at "ben at sixg dot com's" comment at: http://www.php.net/manual/en/function.gmmktime.php
EXCERPT:
For most intents and purposes you can imagine that mktime() first converts your input parameters to GMT and then calls gmmktime() which produces a GMT timestamp.
So, time() always will return the same thing at the same actual moment, anywhere in the world.
gmmktime() and mktime(), when given specific time parameters, convert those time parameters FROM the appropriate timezone (GMT for gmmktime(), local time for mktime()), before computing the appropriate timestamp.
UPDATE:
On some versions of PHP, the timestamp with milliseconds is too large to display as a string. So use the sprintf function to get the string value:
PHP
function getTimestamp($asString=false){
$seconds = microtime(true); // false = int, true = float
$stamp = round($seconds * 1000);
if($asString == true){
return sprintf('%.0f', $stamp);
} else {
return $stamp;
}
}
microtime() in php5 returns unix timestamp with microseconds as per microtime() and if the get_as_float argument is not provided, it gives you a string formatted as "msec sec" so the first part is the millisecond part and the second is the second part. Just split it in two and you get the two parts of the timestamp
Simple answer for PHP:
function exact_time() {
$t = explode(' ',microtime());
return ($t[0] + $t[1]);
}
To get millisecond timestamp from PHP DateTime object:
<?php
date_default_timezone_set('UTC');
$d = new \DateTime('some_data_string');
$mts = $d->getTimestamp().substr($d->format('u'),0,3); // millisecond timestamp
PHP 7
This function has its return type declared.
function timestamp_ms(): int {
$times = gettimeofday();
$seconds = strval($times["sec"]);
$milliseconds = strval(floor($times["usec"]/1000));
$missingleadingzeros = 3-strlen($milliseconds);
if($missingleadingzeros >0){
for($i = 0; $i < $missingleadingzeros; $i++){
$milliseconds = '0'.$milliseconds;
}
}
return intval($seconds.$milliseconds);
}
PHP 5
function timestamp_ms() {
$times = gettimeofday();
$seconds = strval($times["sec"]);
$milliseconds = strval(floor($times["usec"]/1000));
$missingleadingzeros = 3-strlen($milliseconds);
if($missingleadingzeros >0){
for($i = 0; $i < $missingleadingzeros; $i++){
$milliseconds = '0'.$milliseconds;
}
}
return intval($seconds.$milliseconds);
}
when you need the millisecond in str format, I think you should use:
public function get_millisecond() {
list($milliPart, $secondPart) = explode(' ', microtime());
$milliPart = substr($milliPart, 2, 3);
return $secondPart . $milliPart;
}
this will fix the bug int some get millisecond example where the milli part is like : 0.056. some example convert the milli part to float, your will get 56 instead of 056. I think some one want 056.
especially when you need the millisecond to order some data.
hope will help. :)
I recently had this problem to get a timestamp in milliseconds. To just multiply the unix timestamp by 1000 did not resolve the problem because i had to compare two database entrys very precicely. Aparently the php datetime object can´t handle milliseconds/microseconds but its stored in the datetime string anyway. So here is my solution:
$dateObject = new \DateTime('2015-05-05 12:45:15.444', new \DateTimeZone('Europe/London'));
$millis = $dateObject->format('v');
echo $dateObject->getTimestamp()*1000+$millis;
This should also work with microseconds if you use format->('u') (and of course multiply the timestamp by 1000000) instead. I hope you find this useful.
Something like this:
$mili_sec_time = $_SERVER['REQUEST_TIME_FLOAT'] * 1000;
Gives float type representing miliseconds from UNIX epoch to starts of the request.
$timestamp = str_replace(".","",number_format((float)microtime(true),2,'.',''));