I have created an array with 10 timestamps each 1 day apart:
$data_points = array();
$now = time();
$one_day = 60 * 60 * 24;
for($i = 1; $i <= 10; ++$i) {
$key = $now - ($one_day * $i);
$data_points[$key] = 0;
}
print_r($data_points);
Array
(
[1328642414] => 0
[1328556014] => 0
[1328469614] => 0
[1328383214] => 0
[1328296814] => 0
[1328210414] => 0
[1328124014] => 0
[1328037614] => 0
[1327951214] => 0
[1327864814] => 0
)
Now I have a array of tasks that have started at various times in the last 10 days, I want to see which day my task fell into.
I was going to loop through each $data_point and see if the start time is greater than the current day and less than the next, then increment that data point
is there a better way to do this?
Thanks
Well, to reduce your search time you could put your data into a binary search tree rather than a simple array.
Whether or not that's worth the trouble depends on how big your data set is. Of course, you'd also have to re-balance your tree every so often as you add new dates.
I think there's a better method.
Assuming you have task starting timestamps in an array, the algorithm will be something like :
for each task starting timestamp
timestamp <- $now - timestamp // you will obtain task age in seconds
timestamp <- timestamp / (60*60*24) // you will obtain task age in days
// round resulting timestamp with a precision of 0 if you want to obtain the task age in integer days.
end for each
In this way you will loop on only one array. This will be less expensive than your method.
Obviously, if your tasks come from a SQL database, there will be a greater solution in SQL.
You can use DateTime class
$now = new DateTime();
$task = new DateTime('2012-02-20');
$interval = $taks->diff($now);
echo 'Here is the position you need:' . $interval->format('%R%a days');
** Updated to avoid use of DateTime as asked in comment **
$now = date('Ymd');
$task = date('Ymd',$tasktime);
$interval = $task - $now;
The interval is the number you expect.
I know this question is old, but since there are no accepted answers, and it seems like a fun question to answer - here we go!
Based on your question, your algorithm has the Big O of O(10n) where n is the number of tasks. This means, that it is fairly efficient compared to a lot of things. As pointed out, a binary search tree would be faster having O(log(n)), however implementing it wouldn't really be worth the saved time during processing. Though, you can make it slightly more efficient and have a resulting O(n) by using something like:
$now = time();
$oneDay = 86400; //60 * 60 * 24
foreach($tasks as $task) {
//assuming now that $task is the timestamp of the task
//extra paranthesis added for easier reading
$dif = $now - ($oneDay * ceil(($now - $task) / $oneDay));
$data_points[$dif]++;
}
The math in the diff is as follows. $now-$task is the difference between the two timestamps in seconds, we divide by $oneDay to get the number of days in the past the task occurred. Now, assuming that $now is the start of a new day, and if an event happened just 12 hours ago it was 'yesterday', we use ceil to round it to the next integer so '.5' becomes '1'. From there, we multiply by $oneDay to get the number of seconds of the days that have passed - to work with the $data_points array that you previously created. We then take that result and subtract it from $now, again to work with your $data_points array. That result gives us a time stamp that we can use that matches those in the array you created, and we use it as the 'key' for it and increment accordingly.
This will prevent you from having to loop through the entire $data_points array for each task, and thus reducing its complexity from O(10n) to O(n).
Anyways, I hope that answer helps explain why your formula isn't that inefficient, but shows how to make it ever so slightly more efficient.
Related
The following code will return the difference between two Carbon dates in minutes:
$carbonNow = Carbon::now();
$diff = $carbonNow->diffInMinutes($someRandomFutureDateVariable);
Which will return a single minute result. But I'm trying to get the difference in a 15 minute increments - such as every timestamp for every 15 minute increment in the result. Pseudo code would be:
[
'2020-10-15 12:45:00',
'2020-10-15 13:00:00',
'2020-10-15 13:15:00',
'2020-10-15 13:30:00',
...
]
In addition, I'd like to be able to set the time difference, so if I didn't want to target a 15 minute increment I could target whatever increment I pass into my function. I'm able to get the difference between two dates, but stuck on returning timestamps per each increment.
carbon::diffInMinutes delivers the minutes and removes the seconds.
The minute difference for a given minute increment can easily be calculated as follows:
$inc = 15; //15 minutes
$carbonNow = Carbon::now();
$diff = $carbonNow->diffInMinutes($someRandomFutureDateVariable);
$diffInc = $diff - $diff%$inc;
Given -
$Foo = new DateTime();
Is it possible to extract the total number of hours (Non-fractional) from this value in a way besides something like...
$Bar = (($Foo->format('Y') * 365) + $Foo->format('d')) * 24
I was hoping for something like
echo $Foo->tHours(); /*Would output the total number of hours since the UNIX clock started.*/
Does something like this exist, or am I just kind of stuck cave-manning like the way I assigned the value to $Bar above?
DateTime has a getTimestamp method, which provides you with a UNIX timestamp (number of seconds elapsed from the epoch). So you could use that to more accurately compute numbers hours (just divide by 60*60).
$Bar = floor($Foo->getTimestamp() / (60 * 60));
echo "Hours since $Foo->format('c') = $Bar"; // Hours since 2015-10-12T18:42:39-04:00 = 401302
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Can anybody tell me what time format is this 635151121709530000 and how to convert, the result is something like 2013-9-18 14:42:50
Thanks
There's not enough info here to convert your number to a time. There are at least two common ways to represent a point in time:
The first (and most common) is that the number represents a count of units of time between the time represented by the timestamp and some "epoch" date. In order to convert it to a date, you'd need two pieces of info: the scale (the amount of time that elapses between the timestamps N and N+1), and a reference timestamp (commonly the epoch date, which is the date/time that the number 0 represents).
Without that info, you would need at least two timestamps, and the date/time each represents. You could then find the difference between them, divide by the number of seconds, and that'll give you the scale. You could then extrapolate to find the epoch date.
The second possibility is that the number is a bit field, where each part of the date is represented by a certain set of bits in the integer.
If that's the case, then you're somewhat screwed; there could be all kinds of math going on to fit the date parts into a bit field. You will have to either ask someone in charge of the system, or if that's you now, examine the code that generates timestamps.
Edit: If we take the numbers you provided in the comments:
635155956336800000 2013-9-24 05:00:33
635155957368670000 2013-9-24 05:02:16
635155968617830000 2013-9-24 05:21:10
635155968728200000 2013-9-24 05:21:12
635155971811300000 2013-9-24 05:26:21
635155972798800000 2013-9-24 05:27:59
635155978347870000 2013-9-24 05:37:14
Let's see if the numbers make sense as counts.
Take the first and last times and find the difference between their respective timestamps.
635155978347870000 - 635155956336800000 = 22011070000 ticks
Divide by the number of seconds separating the two times ((37*60+14) - 33 == 2201 seconds)
22011070000 ticks / 2201 sec = 10000486.142662 ticks/sec
Round to a nice even number, cause timestamps are based on useful intervals unless you're obfuscating. So in your case, it looks like the scale is 10 million ticks per second, or 100ns per tick.
Verify with the other timestamps (in this case, the 5:27:59 one and the 5:00:33):
635155972798800000 - 635155956336800000 == 16462000000 ticks
16462000000 ticks / 10000000 ticks/sec = 1646.2 sec
(27*60+59) - 33 == 1646 sec
So 100ns looks about right. In order to be sure, though, we'd need timestamps further apart. Just to make sure this is indeed a count rather than, say, two 31-bit numbers representing the year and the current second of that year.
Assuming this is a count, if we take the first timestamp and divide by 10 million:
635155956336800000 ticks / 10000000 ticks/sec = 63515595633.6800000 sec
That's 63.5 billion seconds since the epoch. For reference, 32-bit signed timestamps (which number a bit over 2 billion) will run out in 2038, 68 years from the Unix epoch (1970). This number is about ~29.58 times that, or 29.58 * 68 ~= 2011 years.
That'd put the epoch around the beginning of the first century CE. 1 CE is a significant enough date that it'd make sense as the epoch date. I don't feel like doing the math to confirm that, though.
Corresponding with cHao's 10000000 ticks per second, but using a base date of 01/01/0001 as I'd originally suggested:
$values = array(
array(635155956336800000, "2013-9-24 05:00:33"),
array(635155957368670000, "2013-9-24 05:02:16"),
array(635155968617830000, "2013-9-24 05:21:10"),
array(635155968728200000, "2013-9-24 05:21:12"),
array(635155971811300000, "2013-9-24 05:26:21"),
array(635155972798800000, "2013-9-24 05:27:59"),
array(635155978347870000, "2013-9-24 05:37:14"),
);
function convert($date) {
static $monthArray = array(
31,29,31,30,31,30,31,31,30,31,30,31
);
$date = $date / 10000000 / 24 / 60 / 60;
$y = floor($date / 365.2425);
$YYYY = $y + 1;
$z = 365 * $y + floor($y/4) - floor($y/100) + floor($y/400);
$d = $date - $z;
$month = 1;
while (true) {
$d -= $monthArray[$month - 1];
if ($d < 0) break;
$month++;
$dd = $d;
}
$hh = ($dd - floor($dd)) * 24;
$hours = floor($hh);
$mm = ($hh - floor($hh)) * 60;
$minutes = floor($mm);
$ss = ($mm - floor($mm)) * 60;
$seconds = floor($ss);
return sprintf('%04d-%02d-%02d %02d:%02d:%02d', $YYYY, $month, floor($dd), $hours, $minutes, $seconds);
}
foreach($values as $value) {
echo convert($value[0]), PHP_EOL;
}
gives:
2013-09-22 05:00:33
2013-09-22 05:02:16
2013-09-22 05:21:01
2013-09-22 05:21:12
2013-09-22 05:26:21
2013-09-22 05:27:59
2013-09-22 05:37:14
I'm not sure where the 2-day discrepancy comes from, but the output can probably arbitrarily have 2 days added and unless you're playing with extremely historic dates closer to the 0 timestamp mark, then it'd probably be a good enough function to use
I have a table which shows the time since a job was raised.
// These are unix epoch times...
$raised = 1360947684;
$now = 1361192598;
$difference = 244914;
$difference needs to exclude any time outside of business hours (ex, 9-5 and weekends).
How could I tackle this?
The thing you have to do are 3 in numbers.
You take your start date and calculate the rest time on this day (if it is a business day)
You take your end date and calulate the time on this day and
you take the days in between and multiply them with your business hours (just those, that are business days)
And with that you are done.
Find a little class attached, which does those things. Be aware that there is no error handling, time zone settings, daylight saving time, ...
input:
start date
end date
output:
difference time in seconds
adjustable constants:
Business hours
Days that are not business days
Very bad idea, but I had no choice because I'm on php 5.2
<?php
date_default_timezone_set('Asia/Seoul');
$start = 1611564957;
$end = 1611670000;
$res = 0;
for($i = $start; $i<$end; $i++){
$h = date("H", $i);
if($h >= 9 && $h < 18){
//echo date("Y-m-d H:i:s", $i) . "<br>";
$res = $res + 1;
}
}
echo $res;
Use DateTime.
Using UNIX time for this is slightly absurd, and you would have to literally remake DateTime.
Look up relative formats where you can specify the hour on the day, e.g.
$date = new DateTime($raised);
$business_start = new DateTime("09:00"); // 9am today
$business_end = new DateTime("17:00"); // 5pm today
The rest is for you to work out.
Oh, and instead of start/end, you could probably use DateInterval with a value of P8H ("period 8 hours")
The problem with using timestamps directly is that you are assigning a context to a counter of seconds. You have to work backwards from the times you want to exclude and work out their timestamps beforehand. You might want to try redesigning your storage of when a job is raised. Maybe set an expiry time for it instead?
I am developing a quiz site and there is time for x min to answer the quiz. So when user clicks on start quiz link the starttime (current time at this instant) is recored in session. Also the endtime (start_time+ 30 min) is recorded in session and every time he submits a answer the current time is compared with the quiz end time. Only if the current time is less than end_time the answer should be accepted.
How can I get the currentdatetime?
How can I add x minutes to current this datetime?
How can I compare (<=) datetime ?
I think we should use date time. Is it right?
PHP measures time as seconds since Unix epoch (1st January 1970). This makes it really easy to work with, since everything just a single number.
To get the current time, use: time()
For basic maths like adding 30 minutes, just convert your interval into seconds and add:
time() + 30 * 60 // (30 * 60 ==> 30 minutes)
And since they're just numbers, just do regular old integer comparison:
$oldTime = $_SESSION['startTime'];
$now = time();
if ($now < $oldTime + 30 * 60) {
//expired
}
If you need to do more complicated things like finding the date of "next tuesday" or something, look at strtotime(), but you shouldn't need it in this case.
use php builtin functions to get time:
<?php
$currentTimeStamp = time(); // number of seconds since 1970, returns Integer value
$dateStringForASpecificSecond = date('Y-m-d H:i:s', $currentTimeStamp);
?>
for your application that needs to compare those times, using the timestamp is more appropriate.
<?php
$start = time();
$end = $start + (30 * 60); // 30 minutes
$_SESSION['end_time'] = $end;
?>
in the page where the quiz is submitted:
<?php
$now = time();
if ( $now <= $_SESSION['end_time'] ) {
// ok!
}
?>
Use the time() function to get a UNIX timestamp, which is really just a large integer.
The number returned by time() is the number of seconds since some date (like January 1, 1970), so to add $x minutes to it you do something like (time() + ($x*60)).
Since UNIX timestamps are just numbers, you can compare them with the usual comparison operators for numbers (< <= > >= ==)
time() will give you the current time in seconds since 1/1/1970 (an integer), which looks like it should be good.
To add x minutes, you'd just need to add x*60 to that, and you can compare it like any other two integers.
Source: http://us3.php.net/time
This is an old question but I wanted to provide an answer based on the PHP 5.2 DateTime class which I feel is much easier to use and much more versatile than any previous functions.
So how can i get the currentdatetime?
You can create a new DateTime object like this:
$currentTime = new DateTime();
But at this point, $currentTime is a datetime object and must be converted to a string in order to store it in a database or output it.
$currentTime = $currentTime->format('Y-m-d H:i:s');
echo $currentTime;
Outputs 2014-05-10 21:14:06
How can i add x minutes tocurrent this datetime?
You can add x minutes with the modify method:
$currentTime = new DateTime();
$addedMinutes = $currentTime->modify('+10 minutes');
echo $addedMinutes;
Outputs 2014-05-10 21:24:06
How can i comapare (<=) datetime ?
With the DateTime class, you can not only easily compare datetime objects, you can get the difference between them.
$currentTime = new DateTime('2014-05-10 21:14:06');
$addDays = $currentTime->modify('+10 days');
To compare
if ($currentTime >= $addDays) {
//do something//
}
$diffTime = new DateTime('2014-05-10 21:14:06');
$diff = $addDays->diff($diffTime);
$diff = $diff->format('There are %d days difference.');
echo $diff;
Outputs There are 10 days difference.