Perl Date calculations over two months - mysql

i have a report which runs weekly on a friday doing some db queries where data is from monday to friday and producing a table with the results. I am having a problem when the report runs on a friday where the monday is last month. So for example last friday. Friday was the first of august, and the monday was the 28th of july. The below is the date and time portion of my script.
my $date = `date +%Y%m%d`;
chomp($date);
my $time = `date +%H%M%S`;
chomp($time);
my $day = `date +%A`;
chomp($day);
my $time = `date +%H%M%S`;
chomp($time);
my $dispTime = `date +%H:%M`;
chomp($dispTime);
# Set the Dates
my $end = $date;
my $start = $end;
# Check the day and define start and end dates.
if ($day eq "Friday") {
$start = $end - 5;
my #mytime=localtime;
my ($s, $min, $h, $d, $m, $y) = (0, 0, 0, $mytime[3], $mytime[4], $mytime[5]);
my $todayminus5 = strftime "%Y%m%d", $s, $min, $h, $d - 5, $m, $y;
$start = $todayminus5;
In my report logs it prints the date that was calculated and it printed this
Start Date = 2014080,
End Date = 20140801
Does anybody know why this doesnt seem to be able to calculate the date if its over two months?

You should use Time::Piece in conjunction with its sister module Time::Seconds. If you have a reasonably recent version of Perl then it should already be installed as it has been a core module since version 10 of Perl 5.
By the way, you need to subtract four days to get from Friday to the previous Monday!
use strict;
use warnings;
use Time::Piece;
use Time::Seconds 'ONE_DAY';
my $now = localtime;
if ($now->wdayname eq 'Fri') {
my $monday = ($now - ONE_DAY * 4)->strftime('%Y%m%d');
# etc.
}

I would rework the approach you're taking - you're doing multiple invocations of date which is probably a warning sign in the first place. You've got a whole lot of edge cases - subtracting '5' from your days will get you a negative number if it's early in the month - which will break things - but you'll have similar problems when the year changes.
I won't contradict the previous post, but I'd instead suggest you simplify:
my $ONE_DAY_s = 60 * 60 * 24;
my $now = time();
my $then = $now - 4*$ONE_DAY_s;
my ( $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($now);
$year += 1900;
print "Now: $year $mon $mday\n";
( $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($then);
$year += 1900;
print "Then: $year $mon $mday\n";
(transcribed, rather than pasted so beware typos).
You can use $wday to figure out if it's a friday.
Modules exist to do this as well though - I would be very wary of using repeated invocations of an external command, and then trying to mangle the results.

You can use the Datetime module to get the start date and end date
Example:
use strict;
use warnings;
use DateTime;
my $today_date = DateTime->today(); # Current date (Friday)
my $old_date = $today_date->clone()->subtract(days => 4); # First DoW (Monday)
print $today_date, "\n";
print $old_date, "\n";
Outputs:
2014-08-04T00:00:00
2014-07-31T00:00:00

Related

Selecting rows that are within 2 hours from current time

I am using PHP with MySQL and would like to select rows that have a booking time within 2 hours from now. How do I compare what is in my database with the NOW() MySQL function?
I have columns pickupDate in the format yyyy-mm-dd and pickupTime in the format HH:mm (24-hour). I have tried creating a query with NOW() which returns the a 12-hour time as HH:mm:ss e.g. 2019-05-24 07:54:06 . I can't figure out how to format this to 19:54, or if I should use a different function instead.
For example, if the current date and time is 24/05/19 19:54:06, I would like to select rows between 19:54 and 21:54 on this date.
My table structure is:
referenceNo VARCHAR(100)
pickupDate DATE
pickupTime VARCHAR(100)
You need to create a DATETIME compatible value out of your pickupDate and pickupTime (which you can do by CONCATing them together), then you can compare that with a time range from NOW() to 2 hours later:
SELECT *
FROM yourtable
WHERE CONCAT(pickupDate, ' ', pickupTime) BETWEEN NOW() AND NOW() + INTERVAL 2 HOUR
Demo on dbfiddle
To add two hours in php
$hoursnow = date('H:i');
$timestamp = strtotime(date('H:i')) + 60*60*2;
$plusTwohours = date('H:i', $timestamp);
And $PlusTwohours using this variable frame the query like below
Sql Query:
$sqlQuery = 'select * from foodorder where pickupDate=DATE(NOW()) AND pickupTime>='.$hoursnow.' and pickupTime<='.$plusTwohours;
$result = mysql_query($sqlQuery);
variable $result will have the values of query
For Second Scenario: Adding hours to end of the day May 24 23:30:00
This should be handle by two different date for same column pickupDate
$d = new DateTime('2011-01-01 23:30:30');
$startDate = $d->format('Y-m-d H:i:s'); // For testing purpose assigned manually
$starttime = date('H:i');
// Here Process start, storing end date by adding two hours
$enddate1 = strtotime($startDate) + 60*60*2;
$enddate = date('Y-m-d', $enddate1); // Extracting date alone
$endtime = date('H:i', $enddate1); // Extracting time alone
Have to compare start and end date for column pickupDate, here is the query
$sqlQuery = "select * from foodorder where pickupDate>=DATE(".$startDate.") AND pickupDate<=DATE(".$enddate.") AND pickupTime>='".$starttime."' AND pickupTime<='".$endtime."'";
$result = mysql_query($sqlQuery);

SQL(mysql) comparing times not working

I am trying to select the message from a row where the start and end time is the same as $a and $b. But it does not bring any results however when i remove the end time it brings all the results.
I dont understand why its not working.
$a = '16:50:00';
$b = '17:00:00';
echo $times;
$query1 = ("SELECT message FROM db WHERE DATE(starttime) >= '$a' AND DATE(endtime) <= '$b'");
As you say the starttime and endtime columns are of type TIME. Running a DATE() on them will really mess the time up.
SELECT DATE('17:00:00);
will return 2017-00-00 i.e the best date it can make out of a time. Which of course is no use to you at all.
So mod your query to
SELECT message FROM db WHERE starttime >= '$a' AND endtime <= '$b'

optimize sql query inside foreach

I need help optimizing the below querys for a recurrent calendar i've built.
if user fail to accomplish all task where date
This is the query i use inside a forech which fetched all dates that the current activity is active.
This is my current setup, which works, but is very slow.
Other string explained:
$today=date("Y-m-d");
$parts = explode($sepparator, $datespan);
$dayForDate2 = date("l", mktime(0, 0, 0, $parts[1], $parts[2], $parts[0]));
$week2 = strtotime($datespan);
$week2 = date("W", $week2);
if($week2&1) { $weektype2 = "3"; } # Odd week 1, 3, 5 ...
else { $weektype2 = "2"; } # Even week 2, 4, 6 ...
Query1:
$query1 = "SELECT date_from, date_to, bok_id, kommentar
FROM bokningar
WHERE bokningar.typ='2'
and date_from<'".$today."'";
function that makes the foreach move ahead one day at the time...
function date_range($first, $last, $step = '+1 day', $output_format = 'Y-m-d' )
{
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
foreach:
foreach (date_range($row['date_from'], $row['date_to'], "+1 day", "Y-m-d")
as $datespan)
if ($datespan < $today)
Query 2:
$query2 = "
SELECT bok_id, kommentar
FROM bokningar b
WHERE b.typ='2'
AND b.bok_id='".$row['bok_id']."'
AND b.weektype = '1'
AND b.".$dayForDate2." = '1'
AND NOT EXISTS
(SELECT t.tilldelad, t.bok_id
FROM tilldelade t
WHERE t.tilldelad = '".$datespan."'
AND t.bok_id='".$row['bok_id']."')
OR b.typ='2'
AND b.bok_id='".$row['bok_id']."'
AND b.weektype = '".$weektype2."'
AND b.".$dayForDate2." = '1'
AND NOT EXISTS
(SELECT t.tilldelad, t.bok_id
FROM tilldelade t
WHERE t.tilldelad = '".$datespan."'
AND t.bok_id='".$row['bok_id']."')";
b.weektype is either 1,2 or 3 (every week, every even week, every uneven week)
bokningar needs INDEX(typ, date_from)
Instead of computing $today, you can do
and date_from < CURDATE()
Are you running $query2 for each date? How many days is that? You may be able to build a table of dates, then JOIN it to bokningar to do all the SELECTs in a single SELECT.
When doing x AND y OR x AND z, first add parenthes to make it clear which comes first AND or OR: (x AND y) OR (x AND z). Then use a simple rule in Boolean arithmetic to transform it into a more efficient expression: x AND (y OR z) (where the parens are necessary).
The usual pattern for EXISTS is EXISTS ( SELECT 1 FROM ... ); there is no need to list columns.
If I am reading it correctly, the only difference is in testing b.weektype. So the WHERE can be simply
WHERE b.weektype IN ('".$weektype2."', '1')
AND ...
There is no need for OR, since it is effectively in IN().
tilldelade needs INDEX(tilldelad, bok_id), in either order. This should make the EXISTS(...) run faster.
Finally, bokningar needs INDEX(typ, bok_id, weektype) in any order.
That is a lot to change and test. See if you can get those things done. If it still does not run fast enough, start a new Question with the new code. Please include SHOW CREATE TABLE for both tables.

MySQL current date between 2 set dates

I need some help with a project I'm working on.
There's a table with 2 dates: date1 and date2 (easier)
Now I need to show all rows where the current date is between date1 and date2.
What I have so far is:
$date = date(Y-m-d);
$sql = 'SELECT * FROM boekingen WHERE "$date" BETWEEN date1 AND date2';
but this doesn't work. Although if I replace "$date" with 2017-01-06 it does work. Now how do I solve this problem?
Thanks in advance!
You need to put quotes around the argument to date():
$date = date('Y-m-d');
And you need to wrap the string you assign to $sql in double quotes, otherwise the $date variable won't be expanded.
$sql = "SELECT * FROM boekingen WHERE '$date' BETWEEN date1 AND date2";
What is the difference between single-quoted and double-quoted strings in PHP?
The manual on date() is clear as to its syntax and using quotes around the arguments.
http://php.net/manual/en/function.date.php
Since yours has none, PHP is assuming you have them pre-defined as constants.
Error reporting would have thrown you the following:
Notice: Use of undefined constant Y - assumed 'Y' in /path/to/file.php on line x
Notice: Use of undefined constant m - assumed 'm' in /path/to/file.php on line x
Notice: Use of undefined constant d - assumed 'd' in /path/to/file.php on line x
Examples taken from Example #4 date() Formatting from the manual:
<?php
// Assuming today is March 10th, 2001, 5:16:18 pm, and that we are in the
// Mountain Standard Time (MST) Time Zone
$today = date("F j, Y, g:i a"); // March 10, 2001, 5:16 pm
$today = date("m.d.y"); // 03.10.01
$today = date("j, n, Y"); // 10, 3, 2001
$today = date("Ymd"); // 20010310
$today = date('h-i-s, j-m-y, it is w Day'); // 05-16-18, 10-03-01, 1631 1618 6 Satpm01
$today = date('\i\t \i\s \t\h\e jS \d\a\y.'); // it is the 10th day.
$today = date("D M j G:i:s T Y"); // Sat Mar 10 17:16:18 MST 2001
$today = date('H:m:s \m \i\s\ \m\o\n\t\h'); // 17:03:18 m is month
$today = date("H:i:s"); // 17:16:18
$today = date("Y-m-d H:i:s"); // 2001-03-10 17:16:18 (the MySQL DATETIME format)
?>
Use something like this
$date = date(Y-m-d);
$sql = 'SELECT * FROM boekingen WHERE STR_TO_DATE(\'$date'\', \'%m/%d/%Y\') BETWEEN date1 AND date2';
Make sure that date2 is greater than date1.
date = date(Y-m-d);
$sql = 'SELECT * FROM boekingen WHERE "$date"
That is the code on your question.
Using a single quote for string in php will not expand the variable.
Either use double quotes and single quotes around $date or concatenate eg
$sql = 'SELECT * FROM boekingen WHERE "' . $date .'"
Or sprintf
$sql = sprintf('SELECT * FROM boekingen WHERE "%s", $date)

max value from varchar date

I need to find max date from a table(mysql database). I am storing my date as varchar.
select max(completion_date) from table_name returns wrong value.
http://sqlfiddle.com/#!9/c88f6/3
Assuming the date time format you have in your fiddle (e.g. '12/19/2012 05:30 PM') then:
select max(STR_TO_DATE(completion_date, '%m/%d/%Y %l:%i %p')) from test;
http://sqlfiddle.com/#!9/c88f6/15
It's unclear if you want to factor the time into your rankings or just the date. This example accounts for time too, but you can remove that part of the formatter if desired.
I am not sure why you would want to keep it as varchar not date.
But this will work for varchar:
SELECT completion_date
FROM test
ORDER BY STR_TO_DATE(completion_date, '%m/%d/%Y') DESC LIMIT 1;
http://sqlfiddle.com/#!9/c88f6/10
<?php
// Store dates
$dates = array();
// Loop through and transfer the result set
foreach ($result as $row => $data) {
$dates[$row] = $data['date'];
}
// Sort the array
usort( $dates, "date_sort_function" );
// Max is last date in array.
foreach ($dates as $date) {
$max = $date;
}
?>
Well, something like that. It is a php script and all you have to provide is the sorting function which returns 0 if equal, 1 if older, and -1 if earlier.