Use PHP to change multiple number to another number - php

In text, i have a lot of time number, then i want to change hour to another timezone (+6), example :
00:15 => 06:15
01:00 => 07:00
... and so on.
I'm trying this :
$result = str_replace(
array("00:","01:","02:","03:","04:","05:","06:","07:","08:","09:","10:","11:","12:","13:","14:","15:","16:","17:","18:","19:","20:","21:","22:","23:"),
array("06:","07:","08:","09:","10:","11:","12:","13:","14:","15:","16:","17:","18:","19:","20:","21:","22:","23:","00:","01:","02:","03:","04:", "05:"),
$text
);
echo $result;
But 18: will replace with 04: because php replace 18: to 22: then continue replace 22: to 04:
How to solved this, thank you.
// Edit : To #user3414969 and #Medda86: $text is the data i'm get from another site, that mean i can not control the source, only way to do is replace
// Edit 2 : Here is content : http://bongdatv.net/test.php
// Edit 3: Please solve this problem with replace way, not calculation number way.

I think best is to use the timestamp format, add the time and get out the new time from that.
http://php.net/manual/en/function.time.php

$time = array("00:","01:","02:","03:","04:","05:","06:","07:","08:","09:","10:","11:","12:","13:","14:","15:","16:","17:","18:","19:","20:","21:","22:","23:");
$required_time = array();
foreach($time as $t){
$hour = $t."00"; // 00 appending 0 minites
$hours_plus = 6; // adding 6 hours
$required_time[] = date('H:', strtotime($hour)+($hours_plus*60*60));
}
echo "<pre>";
print_r($required_time);
echo "</pre>";

Optimal way is as suggested by Medda86
However, you can try upon this way
$array = ("00:","01:",....);
//Then you can loop over array and add the time
for($i=0 ; $i < sizeof($array);$i++){
$array[$i] = intval($array[$i]+6)%24;
if($array[$i] < 10)
$array[$i] = str_pad($array[$i],2,'0',STR_PAD_LEFT).':';
else
$array[$i] .= ':';
}

Try this:
$yourArr = array('00:15','01:00','00:30');
foreach ($yourArr as $key => $value) {
$timestamp = strtotime($value) + 60*60*6; // add hours as per your need.
$time = date('H:i', $timestamp);
$newArr[] = $time;
}
echo "<pre>";
print_r($newArr);
Result is:
Array
(
[0] => 06:15
[1] => 07:00
[2] => 06:30
)

Related

How to subtract time from time array using php?

Hello seniors I have a question related to some PHP script.
I have an array containing time => ['12:10', '4:16', '2:5'] and have one html form containing input field of type 'number'.
I want when I enter some value in my form input field for example I enter 7, so after submitting the form in back-end the number 7 which i enter in input field is subtracted from the array which I mentioned above and I will get the result array like:
['5:10', '4:16', '2:5']
I have tried something like that but not able to implement my logic
$val = array(1, 0, 2, 1, 1);
$subtract = 3.5;
foreach ($val as $key => $item) {
if ($subtract >= $item) {
$subtract -= $item;
$val[$key] = 0;
} else {
$val[$key] -= $subtract;
$subtract = 0;
}
}
Any kind of help is highly appreciated
You can use Carbon library for date/time manipulation:
<?php
use Carbon\Carbon;
$times = ['17:46', '03:05', '21:56'];
$timeshift = 3;
$new_times = array_map(
fn($t) => Carbon::createFromFormat('H:i', $t)
->subHours($timeshift)
->format('H:i'),
$times
);
Test Carbon library online
No need for library, just convert your first array to seconds: 1 hour = 3600 ; 1 minute = 60 ; 12:10 is 12 x 3600 + 10 x 60, then you do the same thing to your $_POST value, then use gmdate() to retrieve the original format of your array
$myTimes=array('12:10', '4:16', '2:5');
//do the math
$splittedTime = explode(":", $myTimes[0]); //in your case
$timeInSeconds = $splittedTime[0] * 3600 + $splittedTime[1] * 60 ;
//do the same thing to your your $_POST value if needed or simply
$totalReduceby = 7 * 3600;
// get new total of seconds
$newTime= $timeInSeconds - $totalReduceby;
$result = ltrim(gmdate("H:i", $newTime),0); //ltrim to remove the leading 0
$myTimes=array($result, '4:16', '2:5');
//print_r($myTimes);
time => ['12:10', '4:16', '2:5']
[...]
the number 7 which i enter in input field is subtracted from the array
I will get the result array like: ['5:10', '4:16', '2:5']
Your example is a little ambiguous. Do you only want to subtract the field value from the first element of the array, always? Or only from those elements which are greater than the submitted value?
It's pretty straightforward to subtract minutes from a mm:ss time string; simplest is probably to generalize so that the amount to subtract is also allowed to be mm:ss instead of always being a whole number of minutes. I would just explode both of them, turn them into total seconds (minutes*60+seconds), subtract those, and then turn back into mm:ss. Both conversions might be worth their own functions:
function mmssToSeconds($timeStr) {
if (str_contains($timeStr, ':')) {
list($min, $sec) = explode(':', $timeStr);
} else {
list($min, $sec) = array($timeStr, 0);
}
if ($min < 0) {
return 60*$min - $sec;
} else {
return 60*$min + $sec;
}
}
function secondsToMmss($seconds) {
$abs = abs($seconds);
$sgn = $seconds / $abs;
$min = floor($abs / 60);
$sec = $abs % 60;
return ($sgn < 0 ? '-' : '').sprintf('%d:%02d', $min, $sec);
}
And then the subtraction is easy:
function subtractMinutes($from, $delta) {
return secondsToMmss(mmssToSeconds($from) - mmssToSeconds($delta));
}
If you want to subtract from each element that is big enough, you could use a loop like this:
foreach ($ary['time'] as $i => $t) {
if ((int)$t > $subtract) {
$ary['time'][$i] = subtractMinutes($t, $subtract);
}
}
The comparison works because the cast from string to int ignores everything after the first non-digit, so '12:10' just becomes 12, which is > 7.

PHP invoice number with alpha numeric increment

The invoice number looks like this INV{Year}{Month}-1A Ex: INV202201-1A
The suffix 1A's numerical value can only go up to 9. Then the Alphabet should change to B, then the numerical value again goes to 9B then has to change to C & so on. Also when the month changes the prefix should change back to 1A. I've already tried adding all alphabets to an array but I can't seem to figure it out.
I would really appreciate it if someone can point me out the right logic for this.
The total of 1A to 9Z is 234.
The data for $usedPostfix should be from the database or stored somewhere else.
$usedPostfix = array(
"202112" => 220,
"202201" => 10,
"202202" => 0,
);
This is where we find the unused postfix to be returned.
$date = date_format(new DateTime(), 'Ym');
function getInvoice($counter, $date)
{
foreach (range('A', 'Z') as $char) {
for ($i = 1; $i < 10; $i++) {
if ($counter > 0) {
$counter--;
continue;
}
return "INV" . $date . "-" . $i . $char;
}
}
}
$date is using Ym format. (e.g: 202201)
Examples:
Using $date
echo getInvoice($usedPostfix[$date], $date); // OUTPUT: INV202201-2B
Using custom $date (* for example purpose)
echo getInvoice($usedPostfix["202112"], $date); // OUTPUT: INV202201-5Y
echo getInvoice($usedPostfix["202202"], $date); // OUTPUT: INV202201-1A

How to take average of times with negative values PHP?

I have an array say:
array("10:10:20", "-20:00:10", "14:15:00", "08:10:00");
I tried using strtime but it is giving me error as it cant convert negative values to timestamp. Is there any another way?
After rereading the question I made a little snippet, the average is a sum of numbers. So i'm guessing this should be correct. To bypass the negative timestamps, you just need to calculate the absolute one, make it negative and add it to the sum.
<?php
$timings = array("10:10:20", "-20:00:10", "14:15:00", "08:10:00");
//$timings = array("-10:10:20", "-10:10:20", "-10:10:20", "-10:10:20");
$totalTime = 0;
foreach($timings as $timing) {
$isNegativeTime = strpos($timing, '-') !== false;
$time = strtotime(str_replace('-', '', $timing));
if ($isNegativeTime) $time *= -1;
$totalTime += $time;
}
$avgTiming = $totalTime / count($timings);
$isNegativeAvgTime = $avgTiming < 0;
$avgTiming = date('h:i:s', abs($avgTiming));
echo ($isNegativeAvgTime ? '-':'').$avgTiming;
<?php
$moredownvotes = array("10:10:20", "-20:00:10", "14:15:00", "08:10:00");
$nb_lol = count($moredownvotes);
for ($i = 0; $i < ($nb_lol - 1); ++$i)
{
$pattern = '/^-(.*)/';
$replacement = '${1}';
$moredownvotes[$i] = preg_replace($pattern, $replacement, $moredownvotes[$i]);
}
print "<pre>";
print_r($moredownvotes);
print "</pre>";
?>
Result :
Array
(
[0] => 10:10:20
[1] => 20:00:10
[2] => 14:15:00
[3] => 08:10:00
)
NOW u can use DateTime functions or w/e u want
$date = DateTime::createFromFormat('H:i:s', $moredownvotes[$i]);
echo date_format($date, 'H:i:s');
**RESULT ** : 10:10:20
PHP.net createFromFormat function

Getting the average of an array of dates differences using PHP

I'm trying to get the average time a user spends on my site using my own built analytics.
I'm using the DateTime class right now but the math seems very sketchy. Say I have an array of login times and logout times.
$array = array(
array("login" => '2012-01-31 10:35:58', "logout" => '2012-02-01 10:35:58'),
array("login" => '2012-02-04 10:35:58', "logout" => '2012-02-05 10:35:58')
);
I want to get the of amount of time between each login and logout, then find the average of all those times.
$total = 0;
$count = 0;
foreach ($array as $timestamp) {
$diff = strtotime($timestamp['logout']) - strtotime($timestamp['login']);
$total += $diff;
$count++;
}
echo "Average session time is ", $total / $count;
For safety's sake, you'd be better off using DateTime::createFromFormat() to do the date->time parsing. Your timestamps are a nice normal format, but strtotime is unreliable when you've got some wonky formats.
As well, this code assumes that all login/logout pairs are fully defined. If you have any where either time is off, you'll end up with some huge outliers as those'll most likely come out as 0, rather than a normal "modern" timestamp.
You could do something like:
$sessions = array();
foreach($array as $s) {
$sessions[] = strtotime($s['logout']) - strtotime($s['login']);
}
Now $sessions is an array of all the session lengths in seconds, so if you then do:
$average = array_sum($sessions) / count($sessions);
That is the average session length, in seconds. You could then print that in human-readable format, but I think that's beyond the scope of this question.
The reason I am putting the session lengths in an array first instead of simply summing them up in the loop is that you can then also get other statistics out of it, like longest/shortest sessions, median, etc.
Example using DateTime (tested).
define('DATETIME_FORMAT', 'Y-m-d H:i:s');
$array = array(
array('login' => '2012-01-31 10:35:58', 'logout' => '2012-02-01 10:35:58'),
array('login' => '2012-02-04 10:35:58', 'logout' => '2012-02-06 10:22:58')
);
$total = 0;
$count = 0;
foreach($array as $timeInfo)
{
$loginDatetime = DateTime::createFromFormat(DATETIME_FORMAT, $timeInfo['login']);
$logoutDatetime = DateTime::createFromFormat(DATETIME_FORMAT, $timeInfo['logout']);
$total += ($logoutDatetime->getTimestamp() - $loginDatetime->getTimestamp());
$count++;
}
$average = $total / $count;
echo "Average session duration: ".$average." seconds";
EDIT: initally I've used an array to store diffs, ending with array_sum() / count() to compute the average, but I found Marc B's solution with $total and $count simpler and certainly faster (it may matter here since potentially a lot of login/logout datetimes will be processed). => applied it here.
$array = array( array ("login" => "2012-01-31 10:35:58", "logout" => "2012-02-01 10:35:58"),
array ("login" => "2012-02-04 10:35:58", "logout" => "2012-02-05 10:35:58") );
$amount = 0 ;
foreach( $array as $at )
{
$amount += strtotime( $at[ "logout" ] ) - strtotime( $at[ "login" ] ) ;
}
$average = $amount / count( $array ) ;
echo "amount: $amount seconds\naverage $average seconds\n" ;

how do I concatenate the string values of two arrays pairwise with PHP?

So I have two arrays
Array
(
[0] => test
[1] => test 1
[2] => test 2
[3] => test 3
)
and
Array
(
[0] => test
[1] => test 1
[2] => test 2
[3] => test 3
)
I want to combine them together so I get an array like this?
Array
(
[0] => test test
[1] => test 1 test 1
[2] => test 2 test 2
[3] => test 3 test 3
)
I have found lots of functions like array_merge and array_combine but nothing that does what I want to do.
Any ideas?
Thanks in advance.
Max
You could do it with array_map:
$combined = array_map(function($a, $b) { return $a . ' ' . $b; }, $a1, $a2));
Here is a one line solution if you are using Php 5.3.0+:
$result = array_map(function ($x, $y) { return $x.$y; }, $array1, $array2);
Many answers recommend the array_map way, and many the more trivial for loop way.
I think the array_map solution looks nicer and "more advanced" than looping over the arrays and building the concatenated array in a for loop, BUT - contrary to my expectations - it is much slower than a regular for.
I've run some tests with PHP Version 7.1.23-4 on ubuntu 16.04.1: with two arrays each containing 250k elements of 10 digit random numbers a for solution took 4.7004 sec for 20 runs, while the array_map solution took 11.7939 sec for 20 runs on my machine, almost 2.5 times slower!!!
I would have expected PHP to better optimise the built in array_map feature, than a for loop, but looks like the opposite.
The code I've tested:
// Init the test
$total_time_for = 0;
$total_time_arraymap = 0;
$array1 = [];
$array2 = [];
for ( $i = 1; $i < 250000; $i ++ ) {
$array1[] = mt_rand(1000000000,9999999999);
$array2[] = mt_rand(1000000000,9999999999);
}
// Init completed
for ( $j = 1; $j <= 20; $j ++ ) {
// Init for method
$array_new = [];
$startTime = microtime(true);
// Test for method
for ( $i = 0; $i < count($array1); $i ++ ) {
$array_new[] = $array1[$i] . " " . $array2[$i];
}
// End of test content
$endTime = microtime(true);
$elapsed = $endTime - $startTime;
$total_time_for += $elapsed;
//echo "for - Execution time : $elapsed seconds" . "\n";
unset($array_new);
//----
// Init array_map method
$array_new = [];
$startTime = microtime(true);
// Test array_map method
$array_new = array_map(function($a, $b) { return $a . ' ' . $b; }, $array1, $array2);
// End of test content
$endTime = microtime(true);
$elapsed = $endTime - $startTime;
$total_time_arraymap += $elapsed;
//echo "array_map - Execution time : $elapsed seconds" . "\n";
unset($array_new);
}
echo "for - Total execution time : $total_time_for seconds" . "\n";
echo "array_map - Total execution time : $total_time_arraymap seconds" . "\n";
Question arises than what array_map is good for? One possible answer that comes into my mind, is what if we have a predefined function somewhere, maybe in a 3rd party library, we'd like to apply to the arrays and we don't want to reimplement that function inside our for loop. array_map seems to be convenient in that case, to apply that function on our arrays. But is it any better, than calling the function from a for loop?
I've tested this as well, and looks like truly, array_map excels when using predefined functions. This time array_map took 8.7176 sec, while for loop took 12.8452 sec to do the same job as above.
The code I've tested:
// Init the test
$total_time_for = 0;
$total_time_arraymap = 0;
$array1 = [];
$array2 = [];
for ( $i = 1; $i <= 250000; $i ++ ) {
$array1[] = mt_rand(1000000000,9999999999);
$array2[] = mt_rand(1000000000,9999999999);
}
function combine($a, $b) {
return $a . ' ' . $b;
}
// Init completed
for ( $j = 1; $j <= 20; $j ++ ) {
// Init for method
$array_new = [];
$startTime = microtime(true);
// Test for method
for ( $i = 0; $i < count($array1); $i ++ ) {
$array_new[] = combine($array1[$i], $array2[$i]);
}
// End of test content
$endTime = microtime(true);
$elapsed = $endTime - $startTime;
$total_time_for += $elapsed;
//echo "for external function call - Execution time : $elapsed seconds" . "\n";
unset($array_new);
//----
// Init array_map method
$array_new = [];
$startTime = microtime(true);
// Test array_map method
$array_new = array_map('combine', $array1, $array2);
// End of test content
$endTime = microtime(true);
$elapsed = $endTime - $startTime;
$total_time_arraymap += $elapsed;
//echo "array_map external function call - Execution time : $elapsed seconds" . "\n";
unset($array_new);
}
echo "for external function call - Total execution time : $total_time_for seconds" . "\n";
echo "array_map external function call - Total execution time : $total_time_arraymap seconds" . "\n";
So long story short, the general conclusion:
Calling a predefined function: use array_map, it takes ~40% less time (8.7 sec vs. 12.8 sec )
Implementing the array manipulation right where needed: use for loop, it takes ~60% less time (4.7 sec vs. 11.8 sec).
Have a choice between using a predefined function or (re-)implementing it right where needed: use for loop and implement the required manipulations inside the loop, it takes ~45% less time ( 4.7 sec vs. 8.7 sec. ).
Based on this, in your particular use-case, use for loop and do the concatenation inside the loop body, without calling other functions.
you can do it like
for($i; $i<count($a); $i++)
{
$arr[$i] = $a[$i]." ".$b[$i];
}
Just loop through and assign the concatenation to a new array:
$array1=array("test","test 1","test 2","test 3");
$array2=array("x","y","z","w");
$new_array=array();
foreach (range(0,count($array1)-1) as $i)
{
array_push($new_array,$array1[$i] . $array2[$i]);
}
Assuming the two arrays are $array1 and $array2
for($x = 0; $x < count($array2); $x++){
$array1[$x] = $array1[$x] . ' ' . $array2[$x];
}
If you have data coming from two different querys and they become two different arrays, combining them is not always an answer.
There for when placed into an array ([]) they can be looped with a foreach to count how many, then looped together.
Note: they must have the same amount in each array or one may finish before the other…..
foreach ($monthlytarget as $value) {
// find how many results there were
$loopnumber++;
}
echo $loopnumber;
for ($i = 0; $i < $loopnumber; $i++) {
echo $shop[$i];
echo " - ";
echo $monthlytarget[$i];
echo "<br>";
}
This will then display: -
Tescos - 78
Asda - 89
Morrisons - 23
Sainsburys - 46
You can even add in the count number to show this list item number....
There's no built-in function (that I know of) to accomplish that. Use a loop:
$combined = array();
for($i = 0, $l = min(count($a1), count($a2)); $i < $l; ++$i) {
$combined[$i] = $a1[$i] . $a2[$i];
}
Adapt the loop to your liking: only concatenate the minimum number of elements, concatenate empty string if one of the arrays is shorter, etc.
you loop through it to create a new array. There's no built-in function. Welcome to the wonderful world of programming :)
Hints:
http://pt2.php.net/manual/en/control-structures.foreach.php
You can combine two strings with "."

Categories