How to match a string inside json string wihtout decoding in PHP - php

So I have an API from a Payment gateway which return all the transaction in a day which is in Json format something like this.
{
"status":"1",
"msg":"3 transactions settled on 2016-09-29",
"Txn_details":[
{
"payuid":"58800xxxxxx",
"txnid":"xxxxxx-27410",
"txndate":"2016-09-27 11:06:58",
"mode":"DC",
"amount":"15174.51",
"requestid":"xxxxxxxx",
"requestdate":"2016-09-29 18:17:18",
"requestaction":"capture",
"requestamount":"15174.51",
"mer_utr":"xxxxxxx",
"mer_service_fee":"151.75000",
"mer_service_tax":"22.76000",
"mer_net_amount":"15000.00000",
"bank_name":"VISA",
"issuing_bank":"xxxxxx",
"merchant_subvention_amount":"0.00"
},
{
"payuid":"58800xxxxxx",
"txnid":"xxxxxx-27410",
"txndate":"2016-09-27 11:06:58",
"mode":"DC",
"amount":"15174.51",
"requestid":"xxxxxxxx",
"requestdate":"2016-09-29 18:17:18",
"requestaction":"capture",
"requestamount":"15174.51",
"mer_utr":"xxxxxxx",
"mer_service_fee":"151.75000",
"mer_service_tax":"22.76000",
"mer_net_amount":"15000.00000",
"bank_name":"VISA",
"issuing_bank":"xxxxxx",
"merchant_subvention_amount":"0.00"
}
]
}
So In this Json I have to look for a value called requestid so I have to look for that id by calling the API from the day of payment to next 7 days
and match every record of each day weather it has the requestid . My code is like this
function recursiveUTNRcheck($date_of_payment,$payment_reference,$rec_counter=7){
$date = substr($date_of_payment, 0, 10);
$utrNos ='';$brtoggle=false;
for($i=1;$i<=$rec_counter;$i++){
$sett_date= date('Y-m-d', strtotime($date. ' + '.$i.' days'));
$responsePayu = $this->callPayU($sett_date);
$utrnos=array('status'=>0);
if(!is_null($responsePayu)){
$utrNos = json_decode($responsePayu,true);
foreach ($utrNos['Txn_details'] as $value) {
# code...
if($value['requestid']==$payment_reference){
$utrnos['status']=1;
$utrnos['data'] = $value;
$brtoggle=true;
break;
}
}
if($brtoggle)
break;
}
}
return $utrnos;
}
My problem is if suppose there is like 2000 payment in a day , then the for loop will have to fun for 2000 times and it has to do keep doing it for everyday until it gets it id ,
Worst case could be 7*2000 = 14000 times .
So I was thinking can there be a better way to match the string requestid directly into the json string ? so I think the performance might be bit better than decoding and checking the array.
Thanks

Related

Generating a html table with php using 2 json objects and sorting by date

I have a JSON object with data (date, kms and duration) that I have used to make an HTML table. The data is stored in order via date so its displayed how i want. See below.
Date Km's Duration Part/Service
15/10/19 16.05 01:30:09
14/10/19 16.8 01:30:42
03/10/19 13.47 02:30:36
02/10/19 15.79 01:18:54
30/09/19 17.5 01:26:56
29/09/19 13.15 01:49:38
26/09/19 12.1 01:36:37
I have another JSON object with an array of parts (4th column) and a date. I can't work out how to cycle through both to add the part row in the table in its correct row (before date of first table).
I have tried to run another for each loop within the first table for each loop to check if there is a date before the first table date, and if so insert the row and remove the element from the array so it can't duplicate. I also had to change both dates to strtotime(); otherwise the comparison of dates would only check the first number (days)
foreach($jsonData1 as $elementKey => $element) {
$durMinutes = gmdate("H:i:s", $element->elapsed_time);
$new_date_format = date('d/m/y', strtotime($element->start_date_local));
$kms = round($element->distance / 1000, 2);
foreach($jsonData2 as $eKey => $e) {
$date_ = $e->date_;
$date2_ = strtotime($date_) ;
$date2 = str_replace('20', '', $date2);
if($date2_ < $dateToCompare){
echo "<tr id='".$rowId."'>";
echo "<td></td>";
echo "<td></td>";
echo "<td></td>";
echo "<td>".$date2_."</td>";
echo "</tr>";
/
unset($jsonData2[$eKey]);
}
}
echo "<tr id='".$rowId."'>";
echo "<td>".$new_date_format."</td>";
echo "<td>".$kms."</td>";
echo "<td>".$durMinutes."</td>";
echo "<td></td>";
echo "</tr>";
$rowId++;
}
Json objest added, there was a lot of data so I shortened it. also some rangon inputs i placed in while testing
jsonData1
{"0":{"resource_state":2,"athlete":{"id":17300746,"resource_state":1},"name":"Morning Ride","distance":16046.3,"moving_time":4898,"elapsed_time":5409,"total_elevation_gain":0,"type":"Ride","workout_type":null,"id":2789696693,"external_id":"5017296437_1571097318.gpx","upload_id":2956200741,"start_date":"2019-10-14T23:58:35Z","start_date_local":"2019-10-15T09:58:35Z","timezone":"(GMT+10:00) Australia\/Brisbane","utc_offset":36000,"start_latlng":[-27.39,152.94],"end_latlng":[-27.39,152.94],"location_city":null,"location_state":null,"location_country":"Australia","start_latitude":-27.39,"start_longitude":152.94,"achievement_count":12,"kudos_count":1,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a2789696693","summary_polyline":"dddfDqgnd\\qBb#GTI|Dd#p#`#|APfAF`B[r#Ab#O^kAxBa#b#E\\H`BPx#z#rArBfCdAv#j#lA~#bDZVdAlB`A\\VTBXKt#K|Ho#lBaDvBsCnCeEnHE^Yb#qB~AaC|#wA`AMnAeBxCGt#\\lAdBvClBfB~BrAQF?zBFpES`#sB`Aq#~BCjCIV[b#}AfAcATyAx#oAxAwFq#eAfAK~Ha#vCGrAIdDJnBCpBq#`EG|ALXANo#fBO~#ExB|#rAt#h#t#VzADl#p#gBdBgAd#sBe#mBZCtBN\\r#d#xBdC|CbCnANvAFbE_#c#UqBQp#StF]vA_AdAEb#qAv#}#v#]BFa#l#Eb#_#p#HCzBiBPcADeBHWTGx#\\l#z##Jm#QWVh#\\v#rAdAh#d#E`AYZDS\\#XfAp#rAnC\\#d#oDpAw#x#}#XmD`Aq#|CQt#c#fCw#jBNrAgCW}BYg#f#KGKLMQK#MdAGB_#a#Ut#y#p#mAN#V^KbABj#Mx#s#v#_#~#XjA?ZMl#mA~Ba#VgAJmAOiBn#cAx#m#HmAQo#XG`#BvBaB`BgAt#AtDS|#UHqBiAq#uAeAg#mCBqEq#aAEgCvAgDr#uFPMMoCPm#Cw#Y]FyC_CwB}Bu#_#Yo#?eBFGpBUzAf#lAa#nBqA?_#M]]Qw##iAYq#i#w#}AO{ABoAD[|#cBO_#RB\\OxBsBP]t#_#Va#xBg#\\BLc#jB?rAa#Xf#[`#`#LDTTC#mDcAUbBa#Ze#`#wAnAa#VBXXLEEe#W[TKz#`AJXITDL\\S#_A}AeBSKOFP_#xAl#hBf#VNNZH?#Yq#sAJApBnADIK[cAcAuAg#WiAUYNQj#`Aj#QTD`#f#|Aj#RX`AZX`#|#aAx#l#NAr#mApBkAv#_AvAa#nCo#RD\\M`#s##[d#Mp#g#La#f#o#BIU?cAVr#{AlBc#f#m#Ru#]kDImC~#wOe#][q#k#uGk#eDs#PII?m#Qc#oA_AuDaEmAyDUuA#i#H]|#w#B{#mAyBgAu#ZqAFiABmCEyBIMXy#Ck#We#sAa#uAeC_#aAg#My#sBm#c#mBsB{#qAaA{BSsBzBsD#i#\\gAIiCk#oBq#cAPwDPYvBe#","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"visibility":"everyone","flagged":false,"gear_id":"b6289997","from_accepted_tag":false,"upload_id_str":"2956200741","average_speed":3.276,"max_speed":13.6,"device_watts":false,"has_heartrate":true,"average_heartrate":138.7,"max_heartrate":171,"heartrate_opt_out":false,"display_hide_heartrate_option":true,"elev_high":86,"elev_low":86,"pr_count":1,"total_photo_count":0,"has_kudoed":false},"1":{"resource_state":2,"athlete":{"id":17300746,"resource_state":1},"name":"Morning Ride","distance":16804.8,"moving_time":5069,"elapsed_time":5442,"total_elevation_gain":0,"type":"Ride","workout_type":null,"id":2787313119,"external_id":"5017296437_1571012018.gpx","upload_id":2953665443,"start_date":"2019-10-14T00:17:15Z","start_date_local":"2019-10-14T10:17:15Z","timezone":"(GMT+10:00) Australia\/Brisbane","utc_offset":36000,"start_latlng":[-27.39,152.95],"end_latlng":[-27.39,152.94],"location_city":null,"location_state":null,"location_country":"Australia","start_latitude":-27.39,"start_longitude":152.95,"achievement_count":7,"kudos_count":1,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a2787313119","summary_polyline":"nncfDymod\\{#KwBkBoAe#aGMmAiAsB`#{A?e#sA{A{AsGoDwA[MTKE_BqBmF{DoAqBy#[]w#My#mAcBRyL_#cDmAmEa#y#m#UKs#QsOKOEJAj#YYFcAIqBFc#c#Xa#`ANz#Ov#[j#JpA_ASYaAW#Bx#WBu#qAq#Ec#{B}#qBOm#sAOWwAa#c#_Bg#}#w#oAwBk#e#Qu#cAeAi#\\e#r#Q`Ac#MJzBZTAJg#CZn#Qp#jApCtHhDhAjDvBlErAnAXj#tB`A|#nA`Al#bFZxBtEv#nGAtBQPG`DoANSTKh#i#j#qA`#K?^WIIqBWqARkFsB`#Co#m#NAG_#o#_#Yc#wAa#eA}AQeB\\eCSGo#uAO`Au#tAP^LpAxAzDb#\\b#fAd#A^vAz#RgAXDHd#HH\\`El#hDEzDVT?d#a#zB_A~#fAl#tA|#v#lBjC#|AgAvDUtB_#JcA]SF~AdBHlAo#\\Su#w#`B#n#]CM{#i#x#q#VcALyBr#FbCg#aAw#a#uAf#g#z#hACXP#b#c#C?`#_#`#C^}A~#cA~AVlAZx#hAdBpCxFz#nApAt#Ax#aDnBYbA^?p#s#n#A|#q#`Du#lA`#dA]vANfAS|#`#IvAfARh#f#Ol#wA|A#\\LQh#VFIW_#JAh#XRG?S]SD]XTn#Fd#f#Al#dAt#l#|B_#v#i#RsGj#GVFj#Xc#b#v#xALTUzB_#l#m#R}#RMz#BM{#sAmBsGaM[U}#UgLn#oDp#_#NO\\Kc#^kBEy#gAuBi#g#cAgC{#wAkAC?NEJkAh#SGYb#Uc#uBeAoBKN\\a#P{#e#]cAHQRVVBC_#wD{B{##[qAqBcBH]EmA\\qAG]w#u#HEdA\\h#p#NSKc#HGf#f#NQQq#i#_#FMt#Ep#f#|BgC|#L`#ZbAfB|AzEfAn#z#RlClERCdAaBdAi#f#aAFe#d#GC_#[OiAFj#iAj#]f#Fz#r#Pt#Jy#Mq#JWfBu#lAO^]NDl#aAFj#j#NEk#|#iBX~#`AUAc#f#eAn#_I~#c#xAj#n#G~AfBxBZxBz#vDfCnAxBXTpDm#ZVRf#f#LbHX~B~Ah#t#h#A","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"visibility":"everyone","flagged":false,"gear_id":"b6289997","from_accepted_tag":false,"upload_id_str":"2953665443","average_speed":3.315,"max_speed":11.8,"device_watts":false,"has_heartrate":true,"average_heartrate":140.5,"max_heartrate":167,"heartrate_opt_out":false,"display_hide_heartrate_option":true,"elev_high":79,"elev_low":79,"pr_count":3,"total_photo_count":0,"has_kudoed":false},"2":{"resource_state":2,"athlete":{"id":17300746,"resource_state":1},"name":"Evening Ride","distance":13474.6,"moving_time":4104,"elapsed_time":9036,"total_elevation_gain":0,"type":"Ride","workout_type":null,"id":2761382734,"external_id":"5017296437_1570090432.gpx","upload_id":2926459145,"start_date":"2019-10-03T08:16:33Z","start_date_local":"2019-10-03T18:16:33Z","timezone":"(GMT+10:00) Australia\/Brisbane","utc_offset":36000,"start_latlng":[-27.34,152.98],"end_latlng":[-27.36,152.97],"location_city":null,"location_state":null,"location_country":"Australia","start_latitude":-27.34,"start_longitude":152.98,"achievement_count":5,"kudos_count":4,"comment_count":0,"athlete_count":3,"photo_count":0,"map":{"id":"a2761382734","summary_polyline":"zkzeD{xud\\Kb#GHOFoD\\aANk#GQII?c#cAGKOEYBe#PsCf#y#OKBKFIJCLCp#SdAA`#EHK#cF_#oRmBoPyAs#Bu#M_VcCwJw#ILIn#M|B]zD]zFW`Dc#Le#?gRiBSQEK?MJc#GGIARIDICINHKEIDBFI#GHDKCGHCKCGBHGFPGF#JGHHE?]BIH?#JGBFCK#?JP#GCEI#MGDEKAHINFGGEDGE[PDCH#HFIL#BHEFQBWCk#L^HPI\\AG#DDG?QFBIMAHBNOGDBJRNSKDUAKAJGECHPNH?DJt#d#VOQMq#MEMIEQ?EFFEBHIACIIEO#DFH#FI#JDGF?AMDGI?LXYWMFPCJ#DFm#MEJR#PJGBJOBFAJl#DOIISGAFGCKN{#j#sIt#BxFp#tJ|#RSFOFc#H{Ad#c#DU?K?JM\\Cn#ETBK?K#JEHCI#KDG?JDGCHFIGF#HJKPFI?CIIBIPBHHGBGAMGHGTBHAM?YEn#EDHUDe#?HGTFMBUGFALDKEHBH#IFGOR#s#HUNcAVMV#jCXDDAL]GNL?NMlBAFQGCIFa#FiAK?GJKbBJjALFPSLuBKo##NAP]fCNNJU#g#I?GHGZBLFDHIDa#CMI?EHCXHLHOFaAYTBZAXBHLED[BqA?II?EH#LCXCRIVFPJ?FO?[#WYNCLCVFLHDFCDSGQD]AQGEKf#FKFe#AMG#EHI|#JEBKH_AG[MYHLLBAKFEBNEb#KZERA^GNKE#i#Ho#A[ICAJGz##f#FV?LBNJHPSDQNiC?KESFHGn#GEAIBJGRQzAEILEBq#Da#NYBQBHCm#DIvARhADzCTlFn#dIv#PBFLF#JCrB?jFl#pKbA~NfApFh#DIDe#Jm#B_#?YBQVWPAt#H^ClBa#~#UL?JFZt#LNRJ`#?h#GtA_#jIeBbA`#zCbBLHN`#E`#Ur#S^iAfBoB|E~#fAj#dBj#pA\\Nn#Mb#?RHRRFRHv#XlAFv#JDf#IZO`#[bBMVRTd#D^DjADXTPpAb#nAh#HJHL?PyAtCOZ#r#L|#DJ\\Ph#J|##hAMf#OL[JMd#}#hByAZG\\[JEjA?HEDMBc#BGJGV_#HCn#o#TC~#DtAZPNr#Rr#G`AYrAGfA?X?fAv#RAFGLo#JuAF_BD]GAZcCXoFs#A_BOgC[CSHi#F_AJk#JA\\Bn#RvX~BlHt#rAHPBxA\\hHv#nDh#Z\\nAdAxDrEjIjJXb#QKCK","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"visibility":"everyone","flagged":false,"gear_id":"b6289997","from_accepted_tag":false,"upload_id_str":"2926459145","average_speed":3.283,"max_speed":22.9,"device_watts":false,"has_heartrate":true,"average_heartrate":112.7,"max_heartrate":159,"heartrate_opt_out":false,"display_hide_heartrate_option":true,"elev_high":97,"elev_low":97,"pr_count":3,"total_photo_count":0,"has_kudoed":false},"3":{"resource_state":2,"athlete":{"id":17300746,"resource_state":1},"name":"Morning Ride","distance":15789.8,"moving_time":4281,"elapsed_time":4734,"total_elevation_gain":0,"type":"Ride","workout_type":null,"id":2756177555,"external_id":"5017296437_1569974724.gpx","upload_id":2921078316,"start_date":"2019-10-02T00:06:32Z","start_date_local":"2019-10-02T10:06:32Z","timezone":"(GMT+10:00) Australia\/Brisbane","utc_offset":36000,"start_latlng":[-27.39,152.94],"end_latlng":[-27.39,152.94],"location_city":null,"location_state":null,"location_country":"Australia","start_latitude":-27.39,"start_longitude":152.94,"achievement_count":14,"kudos_count":3,"comment_count":0,"athlete_count":1,"photo_count":0,"map":{"id":"a2756177555","summary_polyline":"~qcfDorod\\SLMr#c#v#c#ZmAUmBoB]M_AQiBBiCOE]H_FGUC_B\\iB?q#GvAa#jBOvCgAlAIZa#R}#DiAa#_BmBs#oAcDkBNQL?f#Xx#RfDrDvA~#RGD_Ah#Wl#IBKm#WeBOy#iAO{#_#Hg#Qe#]QW_#uAyA}#cAyAeByAuAY{#]o#cAa#CWMk#yA[Yw#uASkCLy#GoAF]j#mA#u#Vu#PUPHx#Sh#CXUdAa#tCxA|#|#l#Tj#_#NUXQR]ZQpADlA]NJDqAJOBl#FA?c#HFFVJHDEHs#?{#ZgAKOuAGqAn#_Ft#yDgBEIBYKQ{#PQw#aAaC][i#wA#SJMb#ITTHI?OSQs#MQiAWq#yBsCc#KOJWjAA\\GDc#{#Cs#Dk#lAeCLk#OY}#CQg#IaAoAeAM[Ky#EgBRwBZMnDkC`#{AZeEbAq#f#Jr#h#hAhB~#LfBUfANrA\\HL`F~BZj#LbA\\Rf#DbBjBzBzCAh#Gh#u#nCL`GIpAGb#IL_AB}#i#y#w#kBUYa#Iu#S#i#_#u#MQ#a#PM_#qAg#g#mAsAa#eA{#{A{#qACGg#Yo#m#UKS#Ul#GOSy#I[RWh#MAI[JaAV[VGUG[N_#`#K#MkDNSdBCcC#_BjASp#QdB?xAJ|AEt#Sh#c#VaAAq#JeAi#Si#Kh#N|AIrAiAnCLp#ARc#~#CNBp#JXUC]UO_#E[KESNHb#CVMAu#mAQM_##OG{#aDIo#]_#Mi#mAQKKI{#_#g#}Ag#sAiA_AiBi#c#Y_Aa#W]k#]V_#l#S^C^WDQMDr#AbA`#Z?Ha#GGDZr#Ur#pArCtHjD`AtCzB`FnAbAd#v#vB~#r#jARRt#`#ZDxDLtBzD`AtEL`AWRSbH]Vk#AKFKLKp#g#l#_B`#EIZKuBc#yANiFwBRD?K]_#REBKIW]Qm#s#sA_#iAwASiB\\_CYO[mAGGKBQdAk#dATh#JjAV\\Pt#v#jB^Xf#bAb#CJLFRC`#LXx#L?JQHu#Nn#NL^rDd#`ADzAIrEXhAQnAg#Hi#BIJ?v#z#XdA`#r#x#f#jAhB|#z#tDdC\\l#lAdAdBRxA\\zDzB`At#Jl#^x#RR`BGvAc#f#x#d#RxBBfDT`C|Al#x#l#D","resource_state":2},"trainer":false,"commute":false,"manual":false,"private":false,"visibility":"everyone","flagged":false,"gear_id":"b6289997","from_accepted_tag":false,"upload_id_str":"2921078316","average_speed":3.688,"max_speed":11.3,"device_watts":false,"has_heartrate":true,"average_heartrate":135.4,"max_heartrate":170,"heartrate_opt_out":false,"display_hide_heartrate_option":true,"elev_high":103,"elev_low":103,"pr_count":4,"total_photo_count":0,"has_kudoed":false}}
jsonData2 (rows to add to the original table during construction)
[
{
"component":"fork",
"date_":"21\/10\/2019",
"servicetype":"gfhfh",
"notes":"fhgfghfgh"
},
{
"component":"fork",
"date_":"02\/10\/2019",
"servicetype":"gfhfh",
"notes":"fhgfghfgh"
},
{
"component":"fork",
"date_":"03\/06\/2019",
"servicetype":"gfhfh",
"notes":"fhgfghfgh"
},
{
"component":"fork",
"date_":"18\/02\/2019",
"servicetype":"gfhfh",
"notes":"fhgfghfgh"
},
{
"component":"fork",
"brand":"ppiopoip",
"date_":"16\/10\/2019"
},
{
"component":"fork",
"brand":"ppiopoip",
"date_":"16\/10\/2019"
}
]
I'm hoping there is an easier optin to do this as I think my attempt is way off?
**
I have found an error and updated the code to reflect, the second and first date formats were incorrect. I have changed $date2 to the correct format by replacing 20 from 2019 to 19.
It works beter but only compares the first numbers "dd" and doesn't take the month and year into consideration.
I have found a solution but would be happy to hear any other options.
I have used substr() to break down the dates and compare the year first, month and then days. I will just post the if statements below that I used, posted in place of the original if statement. The rest of the code is identical.
if(substr($date2,6,2) >= substr($date1,6,2)){
if(substr($date2,3,2) >= substr($date1,3,2)){
if(substr($date2,0,2) >= substr($date1,0,2)){

How to iterate efficiently when some sub intervals results are known

You have a function that always inputs an interval (natural numbers in this case), this function returns a result, but is quite expensive on the processor, simulated by sleep in this example:
function calculate($start, $end) {
$result = 0;
for($x=$start;$x<=$end;$x++) {
$result++;
usleep(250000);
}
return $result;
}
In order to be more efficient there is an array of old results, that contains the interval used an the result of the function for that interval:
$oldResults = [
['s'=>1, 'e'=>2, 'r' => 1],
['s'=>2, 'e'=>6, 'r' => 4],
['s'=>4, 'e'=>7, 'r' => 3]
];
If I call calculate(1,10) the function should be able to calculate new intervals based on old results and accumulate them, In this particular case it should take the old result from 1 to 2 add that to the old result from 2 to 6 and do a new calculate(6,10) and add that too. Take in consideration that the function ignores the old saved interval from 4 to 7 since it was more convenient to use 2-6.
This is a visual representation of the problem:
Of course in this example, calculate() is quite simple and you can just find particular ways to solve this problem around it, but in the real code calculate() is complex and the only thing I know is that calculate(n0,n3)==calculate(n0,n1)+calculate(n1,n2)+calculate(n2,n3).
I cannot find a way to solve the reuse of the old data without using a bunch of IF and foreach, I'm sure there is a more elegant approach to solve this.
You can play with the code here.
Note: I'm using PHP but I can read JS, Pyton, C and similar languages.
if you are certain that calculate(n0,n3)==calculate(n0,n1)+calculate(n1,n2)+calculate(n2,n3), then it seems to me that one approach might simply be to establish a database cache.
you can pre-calculate each discrete interval, and store its result in a record.
$start = 0;
$end = 1000;
for($i=1;$i<=$end;$i++) {
$result = calculate($start, $i);
$sql = "INSERT INTO calculated_cache (start, end, result) VALUES ($start,$i,$result)";
// execute statement via whatever dbms api
$start++;
}
now whenever new requests come in, a database lookup should be significantly faster. note you may need to tinker with my boundary cases in this rough example.
function fetch_calculated_cache($start, $end) {
$sql = "
SELECT SUM(result)
FROM calculated_cache
WHERE (start BETWEEN $start AND $end)
AND (end BETWEEN $start AND $end)
";
$result = // whatever dbms api you chose
return $result;
}
there are a couple obvious considerations such as:
cache invalidation. how often will the results of your calculate function change? you'll need to repopulate the database then.
how many intervals do you want to store? in my example, I arbitrarily picked 1000
will you ever need to retrieve non-sequential interval results? you'll need to apply the above procedure in chunks.
i wrote this:
function findFittingFromCache($from, $to, $cache){
//length for measuring usefulnes of chunk from cache (now 0.1 means 10% percent of total length)
$totalLength = abs($to - $from);
$candidates = array_filter($cache, function($val) use ($from, $to, $totalLength){
$chunkLength = abs($val['e'] - $val['s']);
if($from <= $val['s'] && $to >= $val['e'] && ($chunkLength/$totalLength > 0.1)){
return true;
}
return false;
});
//sorting to have non-decremental values of $x['s']
usort($candidates, function($a, $b){ return $a['s'] - $b['s']; });
$flowCheck = $from;
$needToCompute = array();
foreach($candidates as $key => $val){
if($val['s'] < $flowCheck){
//already using something with this interval
unset($candidates[$key]);
} else {
if($val['s'] > $flowCheck){
//save what will be needed to compute
$needToCompute[] = array('s'=>$flowCheck, 'e'=>$val['s']);
}
//increase starting position for next loop
$flowCheck = $val['e'];
}
}
//rest needs to be computed as well
if($flowCheck < $to){
$needToCompute[] = array('s'=>$flowCheck, 'e'=>$to);
}
return array("computed"=>$candidates, "missing"=>$needToCompute);
}
It is function which returns you two arrays, one "computed" holds found already computed pieces, second "missing" holds gaps between them which must be computed yet.
inside function there is 0.1 threshold, which disqualifies chunks shorter than 10% of total searched length, you can rewrite function to send threshold as parameter, or ommit it completely.
i presume results will be stored and after computing added into cache ($oldResults), which might be of any form (for example database as Jeff Puckett suggested). Do not forget to add all computed chunks and whole seeked length into cache.
I am sorry but i can't find a way without cycles and ifs
Working demo:
link

Get duration using YouTube API

I need to get the video duration using Youtube API V3. My application was working fine with API V3 but now it doesn't work.
I found a working example and it works:
$dur = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=[VIDOID]&key=[API KEY]");
$duration =json_decode($dur, true);
foreach ($duration['items'] as $vidTime) {
$vTime= $vidTime['contentDetails']['duration'];
}
Credits: Youtube API v3 , how to get video durations?
This will return the time format something like this.
PT24M30S
How can I convent this to a readable time. Like 24:30?
I can't believe it, anyone have used DateInterval, why? It's just like this:
$duration = new DateInterval('PT24M30S');
print $duration->format('%H:%i:%s'); // outputs: 00:24:30
Helpful links:
The DateInterval class
DateInterval::format
One possible way is to use the function str_replace();
$stamp = "PT24M30S";
$formated_stamp = str_replace(array("PT","M","S"), array("",":",""),$stamp);
echo $formated_stamp; //should give "24:30"
Bonus content - leading zeros
In order to add leading zeros one must first split the string up with explode(), then format the numbers idividually with sprintf(); and finally add it all together again.
$exploded_string = explode(":",$formated_stamp);
$new_formated_stamp = sprintf("%02d", $exploded_string[0]).":".sprintf("%02d", $exploded_string[1]);
$time_format = "PT24M30S ";
preg_match_all('/(\d+)/',$time_format,$parts);
$hours = floor($parts[0][0]/60);
$minutes = $parts[0][0]%60;
$seconds = $parts[0][1];
echo $hours . ": ". $minutes .":". $seconds;
video resource contains a duration field which is a string of the following format. It will be up to you the developer to reformat it as necessary for your application and needs.
contentDetails.duration
The length of the video. The tag value is an ISO 8601 duration. For
example, for a video that is at least one minute long and less than
one hour long, the duration is in the format PT#M#S, in which the
letters PT indicate that the value specifies a period of time, and the
letters M and S refer to length in minutes and seconds, respectively.
The # characters preceding the M and S letters are both integers that
specify the number of minutes (or seconds) of the video. For example,
a value of PT15M33S indicates that the video is 15 minutes and 33
seconds long.
If the video is at least one hour long, the duration is in the format
PT#H#M#S, in which the # preceding the letter H specifies the length
of the video in hours and all of the other details are the same as
described above. If the video is at least one day long, the letters P
and T are separated, and the value's format is P#DT#H#M#S. Please
refer to the ISO 8601 specification for complete details.
As to how to do it I would have to say remove the PT and the S and replace the M with a :. It will probably require some testing on your part depending on what happens when a value is null. I would do some research into ISO-8061
I use the following function to convert the YouTube duration. Simply replace $yt with the format YouTube provided you and it'll print it out nice and readable.
function ConvertYoutubeVideoDuration($yt){
$yt=str_replace(['P','T'],'',$yt);
foreach(['D','H','M','S'] as $a){
$pos=strpos($yt,$a);
if($pos!==false) ${$a}=substr($yt,0,$pos); else { ${$a}=0; continue; }
$yt=substr($yt,$pos+1);
}
if($D>0){
$M=str_pad($M,2,'0',STR_PAD_LEFT);
$S=str_pad($S,2,'0',STR_PAD_LEFT);
return ($H+(24*$D)).":$M:$S"; // add days to hours
} elseif($H>0){
$M=str_pad($M,2,'0',STR_PAD_LEFT);
$S=str_pad($S,2,'0',STR_PAD_LEFT);
return "$H:$M:$S";
} else {
$S=str_pad($S,2,'0',STR_PAD_LEFT);
return "$M:$S";
}
}
Solution PHP
function covtime($youtube_time){
preg_match_all('/(\d+)/',$youtube_time,$parts);
$hours = $parts[0][0];
$minutes = $parts[0][1];
$seconds = $parts[0][2];
if($seconds != 0)
return $hours.':'.$minutes.':'.$seconds;
else
return $hours.':'.$minutes;
}

how to get all numbers from a string and create a total amount using php

i want to get the total amount of hours that is outputted from our database, but the problem is the values are on string format
ex of the values:
9H:20M
3H:13M
3H:50M
6H:30M
TOTAL:22H:53M
i want to get the total of all the values
and display it afterwards, but i don't know how to segregate the numbers from the string
and then convert it to time format, is there any way for me to achieve
the result i'm looking for using a php script for conversion and segregation of values and data?
Here is a pretty basic solution:
<?php
$times = array("9H:20M", "3H:13M", "3H:50M", "6H:30M",);
$total = 0;
foreach ($times as $time) {
preg_match("#(\d+)H:(\d+)M#", $time, $matches);
$total += 60 * $matches[1] + $mtaches[2];
}
echo $total;
This creates a value $total which contains the total number of minutes. Now you can convert back to H and M.
You can use strtotime or the newer DateTime class, but your current format is not compatible, so you have to some modification before. This is a possible solution:
<?php
$result = 0;
$times = array('9H:20M','3H:13M','3H:50M','6H:30M');
foreach($times as $time) {
preg_match('/^(\d{1,2})H[:]([0-5][0-9])M$/',$time, $m);
$timestamp = strtotime($m[1].':'.$m[2]);
$result+=$timestamp;
}
echo date('H:i',$result);
?>
I think the better approach for this is, to grep the total time directly from DB.

How to efficiently filter datetime column for extracting data?

I am usng sqlite to log data every 5 minutes to a column that is time stamped with and integer in Unix time. The user interface uses php code to extract data in various user selectable time frames which is then plotted using javascript. Charts typically have 12 data/time points and I need to extract data for plotting over different periods of say 1Hr/12Hr/24Hr/12days/month/year. So only need to extract 12 data rows per search. So for a 24Hr plot I need to only extract data at houly intervals (when minutes = 0) similarly for 12day plots at daily intervals (when mins=0 && hours=0) etc.
My php code for 1Hr works fine since the data is logged every 5min giving me 12 rows of data between search start time and end time. What is an efficient way of extracting data for the longer periods when number of rows between start time and end time is greater than 12? I need to further filter the search to efficiently extract only the data I need?
any suggestions - most appreciated - frank
$db = new MyDB(); // open database
$t=time(); // get current time
$q1 = "SELECT TimeStamp,myData FROM mdata WHERE ";
$q2 = " AND TimeStamp <=".$t; // end time
$q3 = " AND TimeStamp >=".($t-3600); // start time 1 hour earlier
$qer = $q1.$q2.$q3; // my search query form above parts
$result = $db->query($qer);
$json = array();
while ($data = $result->fetchArray(SQLITE_NUM)) {
$json[] = $data;
}
echo json_encode($json); // data is returned as json array
$db->close(); // close database connection
I think you should use WHERE date BETWEEN in your search query?
This kind of search could take up a lot of time once data builds up?
Since you already know the exact times you're interested in, you should probably just build an array of times and use SQL's IN operator:
$db = new MyDB(); // open database
$timeStep = 300; // Time step to use, 5 minutes here - this would be 3600 for hourly data
$t = time(); // get current time
$t -= $t % $timeStep; // round to the proper interval
$query = "SELECT TimeStamp,myData FROM mdata ";
$query .= "WHERE TimeStamp IN "
$query .= "(" . implode(",", range($t, $t + $timeStep * 12, $timeStep)) . ")";
$result = $db->query($query);
$json = array();
while ($data = $result->fetchArray(SQLITE_NUM)) {
$json[] = $data;
}
You'll need to do some different math for monthly data - try constructing 12 times with PHP's mktime() function.
Here are the references for the PHP implode() and range() functions I used.

Categories