I have an array $d of postcodes, this generates markers of my google map.
I want only show markers which were created less than 3 seconds, over 3 seconds will be hidden.
$postcodes = array();
$diff = array(); // time difference variable
foreach($stmt as $x){
//////////////time calculation start////////////////////////////
$posts[] = $x['date'];
$timePosted = new DateTime($posts[] = $x['date']);
echo 'Time Posted : '. $timePosted ->format("d-m-Y H:i:s");
echo "</br>";
date_default_timezone_set('Europe/London');
$today = date('d-m-Y H:i:s');
echo 'Current time is : '. $today;
echo "</br>";
$today = new DateTime(date('d-m-Y H:i:s'));
$interval = $timePosted->diff($today);
"Difference " . $interval->d. " days ". $interval->h. " hours ".$interval->i." minutes ".$interval->s." seconds ";
echo "</br>";
//$diff[] = $interval->h. " hours ".$interval->i." minutes ".$interval->s." seconds ";
$diff[] = $interval->s; //last array seconds
/////////////////////time calculation finish here/////////////////////////
global $postcodes;
//$postcodes[] = $x['postcode']; //postcodes
foreach ($diff as $time => $seconds) {
echo var_dump($seconds);
if($seconds >=3){
echo "larger than 3 seconds<br />";
}else{
echo "smaller than 3 seconds.<br />";
$postcodes[] = $x['postcode']; //this need to be globle not working yet
}
}//time foreach loop finish here
} /// main foreach loop finish here
$d=' "'.implode('","',$postcodes).'"'; //postcodes inside $postcode array
I can't believe how simple this can be, it turns out I don't need to write this in php at all, I can just do it in SQL all I need is to add date >= now() - INTERVAL 3 second; to my sql statement. Hope this can help someone.
Related
New here, and to perl as well.
I'm trying to write a perl script to do some data archiving at work. Our directory structure is separated at one level by year, then has every day/month inside that.
So, for example:
\2016\1-1
\2016\1-2
....
\2016\12-20
etc...
I'm trying to make this script usable for every test (some of which are run in the future), so I have a prompt for the user to enter the year, which I use to populate the directory structure in the code. I'm having trouble with the month-date portion.
Usually tests are 3-4 days long. Right now I'm asking the user for the test length, then subtracting one. I do that because a 4 day test starting on the 8th, would be the 8 ,9 ,10, and 11th. If I don't subtract one, and just add the duration to the start date, it would go to the 12th.
I can't figure out how to take a start date and duration, and get that range of dates into an array, that I can then call when I need to find/create directories for the archiving.
Ideally, I'd like to have the user enter the year, start date, and length of the test, then create an array that will hold the month-day for all dates of the test. Then I could call those array dates when I create/find the needed directories.
Right now I'm still working on getting the inputs from the user, so that is all that I have.
Couple notes: I don't have every Perl module available to me. I have been using DateTime, and I'm not 100% sure what other modules I could use. Also, the directory structure does not have leading zeros on the month/date (i.e., 2-5, NOT 02-05).
Here is the input code that I have so far. It gives me a start date of today (which I need to change), and gives me the correct end date based on the test length. As you can see, I have not been able to get very far in this:
use warnings;
use DateTime;
my #test_dates;
print "What NAS?";
my $NAS = <STDIN>;
chomp($NAS);
print "What is the Multi-Mission mode (ops/nonops)?";
my $MM_Mode = <STDIN>;
chomp($MM_Mode);
print "What is the data mode (ops/sim/tst)?";
my $Data_Mode = <STDIN>;
chomp($Data_Mode);
print "Which spacecraft (NPP/J01)?";
my $sc = <STDIN>;
chomp($sc);
print "What LOM is being cleaned?";
my $LOM = <STDIN>;
chomp($LOM);
print "What MDMZ is being cleaned?";
my $MDMZ = <STDIN>;
chomp($MDMZ);
print "How many days is the test?";
my $Length = ( <STDIN> - 1 );
my $date = DateTime->from_epoch( epoch => time );
my $Duration = DateTime::Duration->new( days => $Length );
print "NAS is $NAS\n";
print "Multi-Mission mode is $MM_Mode\n";
print "Data Mode is $Data_Mode\n";
print "LOM is $LOM\n";
print "MDMZ is $MDMZ\n";
printf $date->ymd('/');
print #test_dates;
I don't think you have it clear in your mind exactly what you need, but this should help
use strict;
use warnings 'all';
use Time::Piece;
use Time::Seconds 'ONE_DAY';
print 'Enter start date (YYYY-MM-DD): ';
chomp(my $start = <>);
$start = Time::Piece->strptime($start, '%Y-%m-%d');
print 'Enter number of days: ';
chomp(my $duration = <>);
{
my $end = $start + ONE_DAY * ($duration-1);
die "Period crosses end of year" if $start->year != $end->year;
}
my $date = $start;
while ( --$duration ) {
my $dir = $date->strftime('\%Y\%m-%d');
$dir =~ s/\D\K0+//g;
print $dir, "\n";
$date += ONE_DAY;
}
output
E:\Perl\source>perl date_duration.pl
Enter start date (YYYY-MM-DD): 2016-7-18
Enter number of days: 22
\2016\7-18
\2016\7-19
\2016\7-20
\2016\7-21
\2016\7-22
\2016\7-23
\2016\7-24
\2016\7-25
\2016\7-26
\2016\7-27
\2016\7-28
\2016\7-29
\2016\7-30
\2016\7-31
\2016\8-1
\2016\8-2
\2016\8-3
\2016\8-4
\2016\8-5
\2016\8-6
\2016\8-7
Here is an approach that uses DateTime. You don't need to create a DateTime::Duration object, DateTime does that implicitly for you whenever you use date math.
use strict;
use warnings 'all';
use DateTime;
use feature 'say';
my $duration = 4;
my ($year, $month, $day) = (2016, 4, 9);
my $start = DateTime->new( year => $year, month => $month, day => $day);
my #dates;
foreach my $i ( 0 .. ( $duration - 1 )) {
my $date = $start->clone->add( days => $i )->strftime('\%Y\%m-%d');
$date =~ s/(?<=\D)0+//g;
push #dates, $date;
}
say for #dates;
I left out the user input stuff and just set some values. Basically it builds each day, creates the folder names and puts them into an array.
Output
\2016\4-9
\2016\4-10
\2016\4-11
\2016\4-12
I have few lines in my array #lines in which * shows me the start time of a command (like sync/fetch) and the line with same processID pid and the command without * shows me the end time. They may not be continuous always. I would like to get the startdate and enddate of a particular processID and cmd. Like for usera the cmd sync with processID 11859 started at 2015/01/13 13:53:01.491-05:00 and ended at 2015/01/13 13:55:01.492-05:00
Below is my approach in which I took a hash of array and used processID as key and did split the lines. This works fine only when the start and end lines of a command are continuous , but how can I make it work even when they are not continuous.
my %users;
foreach my $line (#lines) {
if ($line =~ m{(\*)+}) {
($stdate, $sttime, $pid, $user, $cmd) = split ' ', $line;
$startdate ="$stdate $sttime";
}
else {
($eddate, $edtime, $pid, $user, $cmd) = split ' ', $line;
$enddate = "$eddate $edtime";
}
$users{$pid} = [ $startdate, $enddate, $user, $cmd ];
}
Content in #lines:
2015/01/13 13:53:01.491-05:00 11859 usera *sync_cmd 7f1f9bfff700 10.101.17.111
2015/01/13 13:57:02.079-05:00 11863 userb *fetch_cmd 7f1f9bfff700 10.101.17.111
2015/01/13 13:59:02.079-05:00 11863 userb fetch_cmd 7f1f9bfff700 10.101.17.111
2015/01/13 13:55:01.492-05:00 11859 usera sync_cmd 7f1f9bfff700 10.101.17.111
I'm looking at your code and wondering why you're using a hash of arrays.
As far as I'm concerned, the purpose of array is a set of similar but ordered values.
Could you not instead do:
my %processes;
foreach (#lines) {
my ( $date, $time, $pid, $user, $cmd, #everything_else ) = split;
if ( $cmd =~ m/^\*/ ) {
#if command starts with a * - it started.
if ( defined $processes{$pid} ) {
print "WARNING: $pid reused\n";
}
$processes{$pid}{'start_date'} = $date;
$processes{$pid}{'time'} = $time;
$processes{$pid}{'user'} = $user;
$processes{$pid}{'cmd'} = $cmd;
}
else {
#cmd does not start with '*'.
if ( $processes{$pid}{'cmd'} =~ m/$cmd/ ) {
#this works, because 'some_command' is a substring of '*some_command'.
$processes{$pid}{'end_date'} = $date;
$processes{$pid}{'end_time'} = $time;
}
else {
print
"WARNING: $pid has a command of $cmd, where it started with $processes{$pid}{'cmd'}\n";
}
}
}
You might want some additional validation tests in case you've got e.g. a long enough log that pids get reused, or e.g. you've got a log that doesn't include both start and finish of a particular process.
When you assign to %users{$pid} you are presuming that the most recent $startdate and $enddate are both relevant. This problem is exacerbated by the fact that your variables that hold your field values have a scope larger than the foreach loop, allowing these values to bleed between records.
In the if block, you should assign the values of $startdate, $user, $cmd to the array. Individually or as a slice if you like. In the else block you should assign $enddate to it's element in the array.
Regex extra credit: You don't seem to really care if there is more that one * in a record, making the + in the regex superfluous. As an added bonus, without it the capturing group is also of no value. m{\*} should do quite nicely.
I have a long array (1x75000 !) of string data.
In this array, there are repeated strings.
i want to find the array indices and the number of each repeating string.
E.g.
A=['abc' 'efg' 'hij' 'abc' 'hij' 'efg' 'klm'];
the answer should be:
2 times 'abc' at array indices 1, 4
2 times 'efg' at array indices 2, 6
2 times 'hij' at array indices 3, 5
1 time 'klm' at array indices 7
notice the large size of the array (1x75000)
This code should work:
<?php
$array = array('abc','wrerwe','wrewer','abc');
$out = array();
foreach ($array as $key => $value) {
if (!isset($out[$value])) {
$out[$value]['nr'] = 0;
$out[$value]['index'] = array();
}
++$out[$value]['nr'] ;
$out[$value]['index'][] = $key;
}
foreach ($out as $k => $v) {
echo "item ".$k." repeats ".$v['nr'].' times at positions: ';
echo implode(', ', $v['index']);
echo "<br />";
}
But so far I haven't tested in on such big array. In fact I don't think you should operate on such big arrays. You should rather divide it on smaller arrays.
I've tested it on 75000 array using code ( source for generating random string from How to create a random string using PHP? ) :
<?php
$array = randomTexts(75000);
$out = array();
foreach ($array as $key => $value) {
if (!isset($out[$value])) {
$out[$value]['nr'] = 0;
$out[$value]['index'] = array();
}
++$out[$value]['nr'] ;
$out[$value]['index'][] = $key;
}
foreach ($out as $k => $v) {
echo "item ".$k." repeats ".$v['nr'].' times at positions: ';
echo implode(', ', $v['index']);
echo "<br />";
}
function randomTexts($nr) {
$out = array();
$validString = 'abddefghihklmnopqrstuvwzyx';
for ($i=0; $i< $nr; ++$i) {
$len = mt_rand(5,10);
$out[] = get_random_string($validString, $len);
}
return $out;
}
function get_random_string($valid_chars, $length)
{
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = mt_rand(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
It also seems to work but it takes a few seconds
What I'm trying is I have a page which you can input 3 angel integers and submit.
After you submit the data will be saved in database using json encode
{"angle1":"60","angle2":"60","angle3":"90","submit":"Submit"}
The above is what's saved into a row
I used
<?php
$sql = "SELECT * FROM wp_options WHERE option_name LIKE 'angle%' ORDER BY option_name";
$options = $wpdb->get_results($sql);
foreach ( $options as $option )
{
echo '<p><b>'.$option->option_name.'</b> = '
.esc_attr($option->option_value).'</p>'.PHP_EOL;
$line = json_decode($option->option_value, true);
}
echo '<span style="color:#f00;">'.'Angel 1 : '.$line['angle1'].'</span><br>';
echo '<span style="color:#0f0;">'.'Angel 2 : '.$line['angle2'].'</span><br>';
echo '<span style="color:#00f;">'.'Angel 3 : '.$line['angle3'].'</span><br>';
This prints out angel 1 : ## where ## is the angle entered and so on.
I also made a simple 2d piechart which shows the angles.
the problem I'm having is if I submit another 3 angles then my result only shows the MOST RECENT angles entered even if there are two or more in the database.
For example in my database I can see
{"angle1":"60","angle2":"60","angle3":"90","submit":"Submit"}
{"angle1":"60","angle2":"60","angle3":"180","submit":"Submit"}
{"angle1":"30","angle2":"60","angle3":"180","submit":"Submit"}
but the result only prints 30 60 and 180 instead of printing all three.
Anyone mind giving me a hand on how I can print all three data out or at least all three sets of the angles. I believe once I figured that out I can then print out all the piecharts with all the angles instead right now only the most recent angle and the piechart are printed.
Thanks a lot people~
P.S.
I'm so so so stupid I didn't put those echo into the foreach loop but my other question is I believe I need to input my codes below into the foreach loop but there are so many tags is there a way to input all those into the foreach loop instead of doing something like echo canvas id="piechart1" blah blah blah and do it bit by bit?
<canvas id="piechart1" width="100" height="100"></canvas>
<script src="<?php echo get_stylesheet_directory_uri().'/piechart.js'; ?>"></script>
<script>
var chartId = "piechart1";
var colours = ["#f00", "#0f0", "#00f"];
var angles = [<?php echo $line['comp2052_angle1'].','.
$line['comp2052_angle2'].','.
$line['comp2052_angle3'];
?>];
piechart(chartId, colours, angles);
</script>
It not print 3 results, because you put them out of for scope. It only print the last $line because $line will replace every for loops.
To fixed it.
<?php
$sql = "SELECT * FROM wp_options WHERE option_name LIKE 'angle%' ORDER BY option_name";
$options = $wpdb->get_results($sql);
foreach ( $options as $option )
{
echo '<p><b>'.$option->option_name.'</b> = '
.esc_attr($option->option_value).'</p>'.PHP_EOL;
$line = json_decode($option->option_value, true);
// put the echo in for scope
echo '<span style="color:#f00;">'.'Angel 1 : '.$line['angle1'].'</span><br>';
echo '<span style="color:#0f0;">'.'Angel 2 : '.$line['angle2'].'</span><br>';
echo '<span style="color:#00f;">'.'Angel 3 : '.$line['angle3'].'</span><br>';
echo '<hr/>'; // to separate each data
}
You can stored line into array then print their when you want it. for example.
<?php
$sql = "SELECT * FROM wp_options WHERE option_name LIKE 'angle%' ORDER BY option_name";
$options = $wpdb->get_results($sql);
// added to stored line
$line = array();
foreach ( $options as $option )
{
echo '<p><b>'.$option->option_name.'</b> = '
.esc_attr($option->option_value).'</p>'.PHP_EOL;
$line[] = json_decode($option->option_value, true);
}
Then. You can mixed html and php in the pretty ways like code below.
<?php foreach($line as $i => $l): ?>
<canvas id="piechart<?php echo $i?>" width="100" height="100"></canvas>
<script>
var chartId = "piechart<?php echo $i?>";
var colours = ["#f00", "#0f0", "#00f"];
var angles = [<?php echo $l['angle1'].','.
$l['angle2'].','.
$l['angle3'];
?>];
piechart(chartId, colours, angles);
</script>
<?php endforeach; ?>
Put this anywhere in html before the code above
<script src="<?php echo get_stylesheet_directory_uri().'/piechart.js'; ?>"></script>
You can see what I am trying to make here http://perthurbanist.com/website/calendarloader.php. Basically it is a horizontal calendar and you will use arrows to move. What I want to do is have the code display all the months horizontally along with all the days (starting from the current month and day). I know how to get the current day using the date function but I don't know how to make the calendar start at that date. I also want it to load lots of months (maybe 2-3 years worth). How do I do those two things.
<?php
$showday = date("j");
$displaymonth = date("M");
$showmonth = date("n");
$showyear = date("Y");
$day_count = cal_days_in_month(CAL_GREGORIAN, $showmonth, $showyear);
echo '<ul class="calendarnavigation">';
echo '<li class="month">' . $displaymonth . '</li>';
for($i=1; $i<= $day_count; $i++) {
echo '<li>' . $i . '</li>';
}
echo '</div>';
?>
If you know (or are able to calculate how far ahead you want to go in days you could try this:
for($i=0; $i<$numberOfDays; $i++)
{
$timestamp=mktime(0,0,0,date("m"),date("d")+$i,date("Y"));
$day=date("d", $timestamp);
$month=date("m", $timestamp);
$year=date("Y", $timestamp);
...Your display stuff here...
}
On each iteration of the loop the $timestamp will advance one day and using it in your date functions will give you the information about the date that you need to create your display.
Maybe in your case you can use
echo '<ul class="calendarnavigation">';
for($i=0; $i<$numberOfDays; $i++)
{
$timestamp=mktime(0,0,0,date("m"),date("d")+$i,date("Y"));
$showday=date("j", $timestamp);
$displaymonth=date("M", $timestamp);
$showmonth=date("n", $timestamp);
$showyear=date("Y", $timestamp);
if($showday=="1")
{
echo '<li>'.$displaymonth.'</li>';
}
echo '<li>'.$showday.'</li>';
}
echo '</ul>';