In my DB I have UNIX Timestamps as due dates for jobs that need to run. On a given day or a given hour I'd like to know which jobs need to run. I have the following code to query my jobs table:
$job = Model_Job::find('first',
array(
'where' => array(
array('status_id', 1), // active
array('due_date', today)
)))
The last array is just pseudo code of course. I came up with the following code to figure out if a timestamp is today.
date('Ymd', strtotime(Date::forge(time())->get_timestamp())) == date('Ymd', strtotime($job->due_date))
How would I combine that with my query? Is there a better way then looping through the queried array?
Now, this is probably not a good way but it was the first that came to mind.
$today = strtotime('today 00:00');
You can use the date from that snippet and set a WHERE due_date > $today I'm not quite sure how to do that with your database model.
edit: This relies on that you have correct timezone settings in your php configuration.
As sebastian pointed out, this will get all future dates also, but you could simply use the same technique to get the last timestamp of the day
$todaystart = strtotime('today 00:00'));
$todayend = strtotime('today 23:59:59'));
and the use a BETWEEN operator in your SQL-query
Related
Given an arbitrary timestamp (e.g. 2019-02-26 10:30:00) I would like to find the next occurrence of an arbitrary time.
For example, the next occurrence of 12:00:00 will be 2019-02-26 12:00:00 but the next occurrence of 09:00:00 will be the next day at 2019-02-27 09:00:00. The results could be Carbon or Datetime objects. The test time will just be a string as shown.
Is there a way to calculate this in native PHP or PHP Carbon without conditionally boxing in time periods. An obvious way would be to see if the time being tested is past the check time for today, and if it is, taking the result as the check time plus 24 hours (the next day). That feels to me like too much chopping and joining of dates and times, so is there a way to calculate it by considering time to be a simple linear line?
All times will be in a single timezone, with DST. Note: the arbitrary datetimes and check times will stay clear of DST changeovers i.e. 01:00 to 02:00 so hopefully they will not be an issue to take into account.
Short answer is no for PHP (partial answer, I'm no specialist of Carbon but from quick look it's also no, but you can create a macro from following code).
However, with a ternary condition the one-liner is simple enough IMHO (replace the second DateTime($str) with DateTime() if you want to compare with current date and time, and change the >= by > if you want next day when time compared is exactly the same):
$str = '2019-02-26 10:30:00';
$date1 = ( ($a = (new DateTime($str))->setTime(12,00)) >= (new DateTime($str)) ) ? $a : $a->modify('+1 day');
$date2 = ( ($a = (new DateTime($str))->setTime(9,00)) >= (new DateTime($str)) ) ? $a : $a->modify('+1 day');
echo $date1->format('Y-m-d H:i:s'); //2019-02-26 12:00:00
echo $date2->format('Y-m-d H:i:s'); //2019-02-27 09:00:00
quick note: what you gave us is not a timestamp, but a formatted date.
Here is what I am using now through Carbon, which appears to give me the correct results:
$dateTime = Carbon::parse('2019-03-30 17:34:50', 'Europe/London');
$testTime = '16:00:00';
list ($hour, $minute, $second) = explode(':', $testTime);
$nextTimeOccurrence = $dateTime
->copy() // Carbon 1 only
->hour($hour)->minute($minute)->second($second);
if ($dateTime->gt($nextTimeOccurrence)) {
$nextTimeOccurrence = $nextTimeOccurrence->addDay();
}
// $nextTimeOccurrence is the next occurrence of $testTime after $dateTime
The splitting of the time seems clumsy, but might be the best way? The approach is:
Create a timestamp with the test time on the same day as the timestamp I'm checking. This will be the timestamp I am looking for.
If the timestamp I'm checking is after the timestamp created in the previous step, then add a day to it.
I've tested this around DST, and happily Carbon/Datetime keeps the same time when adding a day over a DST period, where a day there would be 25 hours or 23 hours, depending on which way it goes.
I still think there is a more "linear time" way to do this, but this seems simple and robust. Thanks go to #michael-stokoe here at the office for my lead on this.
Currently, I'm trying to parse out dates when messages were received into timestamps. I have the month and day but the year is not specified. The event always occurs at the most recent (human) reading of the time. It works great in most cases to do this:
$time = strtotime("Jan 2 8:38pm");
That returns a date for this year, which is correct. Unfortunately, I get problems when I try to do for example:
$time = strtotime("Dec 31 8:38pm");
That returns a date which hasn't happened yet, and wont happen for the whole rest of the year. Obviously, my message was not sent in the future. I need it to return December 31st of last year.
For weekdays, I had a solution by prepending 'last' before the weekday like so:
$time = strtotime("Last Saturday 8:38pm");
That always returned the time of the last Saturday. However, trying to do the same thing here doesn't work:
$time = strtotime("Last Dec 31 8:38pm");
This returns false. I know to decrement a date by 1 year, I can do this:
$time = strtotime("Dec 31 8:38pm -1 year");
And that works great for Dec 31. However, Jan 2 will now fail:
$time = strtotime("Jan 2 8:38pm -1 year");
One solution I thought of was to subtract off a year (86400 * 365) from the resulting value if it is past today's date. However, this result will fail if we passed over February of a leap year. In that case, we would end up with a time that was ahead by a day.
The best solution I came up with so far is this:
$time = strtotime($raw_time);
if ($time > time()) {
$time = strtotime($raw_time." -1 year");
}
It seems kind of wasteful to make two calls to strtotime which I know is probably not a very efficient function. Is this the most elegant solution?
Is anyone aware of an option in strtotime which forces the dates to be in the past instead of in the future?
Is there another way to parse these dates that I should consider?
Efficiency is important for this because I am going to be parsing a lot of dates with it, but I would also like simple and readable code so I can understand it later.
Your approach is fine, as there is no date format to get what you want. Another approach could be using the DateTime class:
$datetime = new DateTime($raw_time);
if ($datetime > new DateTime()) {
$datetime->modify('-1 year');
}
You could test which one of the two approaches is faster. My guess is that this is a micro-optimization that won't make a lot of difference.
I have a Database and I use Propel to get the data.
Now I have the following problem:
I want to get the date from one Table and add 30 days on it.
So something like this:
$invoicePayDay = $invoice->getCreationDay()->add(30 days)->format('d.m.Y');
I know that I can read the month, day and year separately and can than add 20 days and create a date from it again. but properly there is a better way to do it with Propel like my example?
Return the date as a var than you can do
$date = date('d.m.Y', strtotime('+30 days', strtotime($returnDate)));
MySQL table "flightSched" is connected to time, similar to the one below:
flightNo |day |time |arrivalTimeSec
=============================================
WERE112 |Tuesday | 1:00 |1381186800
FGHG234 |Tuesday |23:00 |1381266000
CGHF345 |Tuesday |00:00 |1381183200
I have a mysql query that select all data between two times. This is the query:
$CurrentTimeMinus30min = date('H:i', strtotime('-30 minutes')); //Current Time minus 30minutes
$CurrentTimeMinus30min = strtotime($CurrentTimeMinus30min);
$CurrentTimePlus4Hours = date('H:i', strtotime('+240 minutes')); //Current Time plus 4 hours
$CurrentTimePlus4Hours = strtotime($CurrentTimePlus4Hours);
$query = $mysqli->query("
SELECT * FROM flightSched
WHERE day = '$currentDay'
AND arrivalTimeSec
BETWEEN '$CurrentTimeMinus30min'
AND '$CurrentTimePlus4Hours'
");
I was advised to used strtotime() function on the time values to be able to use them in a BETWEEN MySQL query. This doesn't seem to be working at all.
Where am I going wrong with this query? Any help will be appreciated.
today I found the same problem with yours (mine about coordinates).
and I found out that in some case, a BETWEEN operator can only be used like this
..... WHERE columname BETWEEN smallervalue AND biggervalue
previously I've tried with the biggervalue at front since I dealt with negative numbers, and it fails.
you might found the same problem with your timestamp.
strtotime returns a timestamp so passing that into the MySQL query, like above, won't work. Try using FROM_UNIXTIME instead.
$query = $mysqli->query("SELECT * FROM flightSched
WHERE day = '$currentDay'
AND FROM_UNIXTIME(arrivalTimeSec) BETWEEN FROM_UNIXTIME($CurrentTimeMinus30min) AND FROM_UNIXTIME($CurrentTimePlus4Hours) " );
EDIT - I hadn't noticed that arrivalTimeSec was also a timestamp. The above mightn't be a workable answer for you, but try it. If it doesn't work, as others say, define what you mean by
This doesn't seem to be working at all.
Is it not returning any rows? Is it returning an error? Can you print out $CurrentTimeMinus30min and $CurrentTimePlus4Hours? Narrow down the potential areas for problems.
Have you tried to encapsulate the between? This could potentially solve your problem:
SELECT * FROM flightSched
WHERE day = '$currentDay'
AND (arrivalTimeSec BETWEEN '$CurrentTimeMinus30min' AND '$CurrentTimePlus4Hours')
Also why not just do:
$CurrentTimeMinus30min = strtotime('-30 minutes');
Or
$CurrentTimeMinus30min = strtotime(date('Y-m-d H:i:00', strtotime('-30 minutes')));
Please send us some examples of what your variables are generating.
Your time calculation with date("H:i",...) and strtotime(..) seems to actually produce the correct results, although there is a much easier way to add/substract n minutes from the current time:
$now = time();
$currentTimeMinus30min = $now - 30*60; // 30 minutes * 60 seconds
$currentTimePlus4Hours = $now + 4*60*60; // 4 hours * 60 minutes * 60 seconds
(I assume your time entries in your database are unix timestamps.)
Your query looks fine, too, but there are a few things to keep in mind:
You have redundant fields in your database (day and time can be calculated from the timestamp)
Working with time variables can easily lead to confusion, as the time passes on and if you have no entries in your database that match the specified time range (-30m to +240m) the result set is empty. So to test the query update the database with current time stamps.
I would suggest the following:
Drop the redundant columns day and time and just use the timestamp as base for your calculations, because the day and time is already included in the timestamp. So just use a simple query like
select * from flightShed
where arrivalTime between $begin and $end
all - fairly simple query question that's been hounding me: How do I query for entries with a date and time only greater than now, or when the query is run (page requested)?
I've seen some examples but they aren't good enough for me to modify. Here's my code:
$todaysDate = date("Y-m-d h:i:s");
$params = array('select'=>'*', 'limit'=>3, 'orderby'=>'t.event_StartDate ASC', 't.event_StartDate < "$todaysDate"' );
An example of the variable "t.event_StartDate" outputs "2010-12-10 22:18:42" so I assume that may be how it's saved in the database.
I suspect I'm not building the date correctly or I need to be using a time function I'm not familiar with in MySQL. Help? This is for outputting a series of events with date and time.
I think you reverse the use <, it should be >
try
SELECT ... WHERE t.event_StartDate>NOW();
/* you don't even need to set $todaysDate */
t.event_StartDate > NOW() don't will returns nothing? a date higher of now lol. I'm confused.